zoukankan      html  css  js  c++  java
  • IOI202021集训队作业DL205. Visual Python++

    有一堆矩形,两两之间边没有公共点(即相离或包含),现在给出左下角和右上角,要求找到一种合法的对应关系。

    (nle 10^5)


    假如存在合法关系,可以贪心构造:把所有点以(x)为第一关键字,(y)为第二关键字排序。维护个以(y)为关键字的集合(S)

    依次加入点。如果是左下角,则加入(S)中;如果是右上角,则在(S)中前驱,匹配之。

    如果存在一种合法对应关系,可以证明这种方法一定可以把这种对应关系还原出来。(同时这也表明了合法的对应关系是唯一的)

    问题是判断是否合法:做以上操作时,如果出现右上角没得匹配左下角则不合法;如果某个时刻集合中出现相等元素(即(y)相等)也不合法。

    判断完这些之后再做一次扫描,如果遇到左下角,将其加入(S)中,并且判断是否和(S)中前驱后继对应的矩形相交;如果遇到右上角,删去其对应的左下角。讨论一下可以证明如果不和前驱后继对应矩形相交,那么不会和别的矩形相交。

    用set维护,时间(O(nlg n))


    为什么C++17CE了但是C++11过了

    using namespace std;
    #include <bits/stdc++.h>
    #define N 100005
    int n;
    struct DOT{int x,y,id;} a[N],b[N];
    bool cmp(DOT p,DOT q){return p.x<q.x || p.x==q.x && p.y<q.y;}
    struct cmpay{
    	bool operator()(int p,int q){return a[p].y<a[q].y;}
    };
    set<int,cmpay> s;
    int p[N],q[N];
    bool find(){
    	sort(a+1,a+n+1,cmp),sort(b+1,b+n+1,cmp);
    	for (int i=1,j=1;i<=n;++i){
    		for (;j<=n && !cmp(b[i],a[j])/*a[j]<=b[i]*/;++j){
    			if (s.find(j)!=s.end())
    				return 0;
    			s.insert(j);
    		}
    		a[0]=b[i];
    		auto t=s.upper_bound(0);
    		if (t==s.begin())
    			return 0;
    		--t;
    		p[*t]=i,q[i]=*t;
    		s.erase(t);
    	}
    	return 1;
    }
    bool its(DOT i,DOT pi,DOT j,DOT pj){
    	if (max(i.x,j.x)>min(pi.x,pj.x) || max(i.y,j.y)>min(pi.y,pj.y))
    		return 0;
    	if (i.x>j.x) swap(i,j),swap(pi,pj);
    	return !(i.x<j.x && i.y<j.y && pj.x<pi.x && pj.y<pi.y);
    }
    bool check(){
    	assert(s.empty());
    	for (int i=1,j=1;i<=n;++i){
    		for (;j<=n && !cmp(b[i],a[j]);++j){
    			auto t=s.upper_bound(j);
    			if (t!=s.end() && its(a[*t],b[p[*t]],a[j],b[p[j]]))
    				return 0;
    			if (t!=s.begin()){
    				--t;
    				if (its(a[*t],b[p[*t]],a[j],b[p[j]]))
    					return 0;
    			}
    			s.insert(j);
    		}
    		s.erase(q[i]);
    	}
    	return 1;
    }
    int ans[N];
    int main(){
    //	freopen("in.txt","r",stdin);
    	scanf("%d",&n);
    	for (int i=1;i<=n;++i) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i;
    	for (int i=1;i<=n;++i) scanf("%d%d",&b[i].x,&b[i].y),b[i].id=i;
    	if (find()==0 || check()==0)
    		printf("syntax error
    ");
    	else{
    		for (int i=1;i<=n;++i)
    			ans[a[i].id]=b[p[i]].id;
    		for (int i=1;i<=n;++i)
    			printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    ECMAScript 6 基础入门
    软件历史版本存档及下载
    arduino 编程基础
    生活中的实验 —— 家庭电路
    电子元件 —— 继电器
    电与磁 —— 电磁铁
    windows cmd 命令行 —— 进程与服务
    计算机硬件、摄影设备、物质、材料英语
    DHCP服务器备份、还原、迁移
    SVN同步
  • 原文地址:https://www.cnblogs.com/jz-597/p/14397620.html
Copyright © 2011-2022 走看看