• CF97B Superset超级集合


    CF97B Superset

    这题主要是构造难想。看看数据范围发现连(O(n^2))都被卡了,然后 考试的名称提醒我 想到了分治。

    坐标按横坐标为关键字排序后找中间的点进行分治不是点分治qwq

    考虑让中间点作一条平行于y轴的直线,让每个点i(mid除外)向这条直线引垂线交于一个点 (S_i),那么这个点一定可以加入。

    原因:

    可行性证明:

    考虑不包含 (S_i) 的点,由于左半边和右半边都已满足条件,当左边的点i和右边的点j组成矩形时,矩形边缘上一定有2个点(S_i,S_j),于是这些S就能使左右合并。

    考虑包含 (S_i) 的点。如果它和点j组成矩形,那么边缘上一定有点 (S_j) ,满足题意。

    分治完了记得去重哦~

    由于点数是 (nlog n) 的级别,所以数组也要开到 (nlog n)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=150005;
    int n,len,tot;
    struct point{
    	int x,y;
    }a[N],ans[N],p[N];
    bool cmp(const point &a,const point &b)
    {
    	if(a.x!=b.x)return a.x<b.x;
    	else return a.y<b.y;
    }
    void msort(int l,int r)
    {
    	if(l==r){ans[++tot]=a[l];return;}
    	if(l>r)return;
    	int mid=(l+r)>>1;
    	msort(l,mid-1);msort(mid+1,r);
    	for(int i=l;i<=r;++i)
    	{
    		point tmp;
    		tmp.x=a[mid].x;
    		tmp.y=a[i].y;
    		ans[++tot]=tmp;
    	}
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)
    		scanf("%d%d",&a[i].x,&a[i].y);
    	sort(a+1,a+n+1,cmp);
    	msort(1,n);
    	sort(ans+1,ans+tot+1,cmp);
    	ans[0].x=ans[0].y=1000000007;
    	for(int i=1;i<=tot;++i)
    	{
    		if(ans[i].x!=ans[i-1].x||ans[i].y!=ans[i-1].y)
    			p[++len]=ans[i];
    	}
    	printf("%d
    ",len);
    	for(int i=1;i<=len;++i)
    		printf("%d %d
    ",p[i].x,p[i].y);
    	return 0;
    }
    
    路漫漫其修远兮,吾将上下而求索
  • 相关阅读:
    myeclipse源码相关操作
    来自一个程序员内心深处的心声
    编程乐趣--汉字转拼音
    MyEclipse下安装FreeMark插件
    java web 加载Spring --web.xml 篇
    注解方式实现声明式事务管理
    spring与struts简单整合案例
    创建对象与对象依赖关系
    几种对数据的处理以及对数据的封装
    Action开发、通配符、路径问题和struts中常量用法
  • 原文地址:https://www.cnblogs.com/zzctommy/p/12350334.html
Copyright © 2020-2023  润新知