• 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;
    }
    
    路漫漫其修远兮,吾将上下而求索
  • 相关阅读:
    【转】高性能网络编程4--TCP连接的关闭
    Kubernetes 用了,延迟高了 10 倍,问题在哪?
    多路复用和多路分用
    网络七层模型与四层模型区别
    Go验证包出错 dial tcp 34.64.4.17:443: i/o timeout
    spring Bean配置的三种形式
    Spring容器IOC初始化过程
    Go 特殊语法
    服务发现的基本原理与比较:Eureka vs Consul vs Zookeeper
    docker 常用命令
  • 原文地址:https://www.cnblogs.com/zzctommy/p/12350334.html
Copyright © 2020-2023  润新知