编程语言
首页 > 编程语言> > loj6481 #6481. 「ICPC World Finals 2017」Visual Python++

loj6481 #6481. 「ICPC World Finals 2017」Visual Python++

作者:互联网

同时也是CF gym101471L。

题目叙述

给定 \(n\) 个矩形的左上和右下,问是否能够还原出一种方案使得举行只包含或相离,不相交。

题解

考虑每个右下的点匹配离他最近的左上的点。
结论是如果有解,这样匹配就是正确的。
剩下问题是看是否只有嵌套关系,考虑按照 \(x\) 从小到大进行扫描线,每次把矩形的上下边界插入到一颗平衡树中。
容易发现,插入时两个纵坐标相邻,删除时两个纵坐标也相邻,那么就一定都是包含关系。

反思

主要反思一下思考过程。
尝试例子花费40分钟。
想起来以前某个圆相关的扫描线题花费20分钟。
想到这样简单的策略再花费20分钟。
中间不知道该怎么办的楞神还有不知道多少分钟。

正确的做法是先思考10分钟。这10分钟不见得需要尝试例子。
然后至少尝试三个例子。
然后水平展开,看看有哪些可能的方式。并且思维导图式地记录下来。
思考一下以往的套路(有时候要结合尝试),理想情况下5分钟应该能想起来。
另外需要对这个问题进行一些类型的描述。文字上的描述和直觉不一定等价。比如这个题可以描述为扫描线。

注意,尝试例子的时候需要假定一种贪心策略,然后尝试找反例。这样思考更有效率。
猜测贪心策略要根据以往经验,不怕错。

代码

要不还是存一下。

#include <cstdio>
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#define fi first
#define se second
#define pii pair<int,int>
#define fail return printf("syntax error\n"),0
using namespace std;
typedef long long LL;
const int MN=1e5+5;
int N;
struct Node{
	int x,y,id;
	Node():x(0),y(0){}
	Node(int _x,int _y):x(_x),y(_y){}
}dot[MN*2];
bool cmp1(const Node &A,const Node &B){return (A.x==B.x)?(A.y<B.y):(A.x<B.x);}
bool cmp2(const Node &A,const Node &B){return A.id<B.id;}
set<pii> s;
int ans[MN];
int lx[MN*2],tx;
vector<pair<pii,bool> > buc[MN*2];
bool cmp(const pair<pii,bool> &x,const pair<pii,bool> &y){
	if(x.se==y.se){
		if(x.se==0)return (x.fi.se-x.fi.fi)>(y.fi.se-y.fi.fi);
		else return (x.fi.se-x.fi.fi)<(y.fi.se-y.fi.fi);
	}else return x.se>y.se;
}
int main(){
	// freopen("l.in","r",stdin);
	// freopen("l.out","w",stdout);
	scanf("%d",&N);
	for(int i=1;i<=2*N;++i){
		scanf("%d%d",&dot[i].x,&dot[i].y),dot[i].id=i;
		lx[++tx]=dot[i].x;
	}
	sort(dot+1,dot+2*N+1,cmp1);
	for(int i=1;i<=2*N;++i){
		if(dot[i].id<=N){
			s.insert(make_pair(dot[i].y,dot[i].id));
		}else{
			auto it=s.upper_bound(make_pair(dot[i].y,1e9));
			if(it==s.begin())fail;
			--it;
			ans[it->se]=dot[i].id-N;
			s.erase(it);
		}
	}
	sort(dot+1,dot+2*N+1,cmp2);
	sort(lx+1,lx+tx+1);
	tx=unique(lx+1,lx+tx+1)-lx-1;
	for(int i=1;i<=2*N;++i)dot[i].x=lower_bound(lx+1,lx+tx+1,dot[i].x)-lx;
	for(int i=1;i<=N;++i){
		buc[dot[i].x].push_back(make_pair(make_pair(dot[i].y,dot[ans[i]+N].y),1));
		buc[dot[ans[i]+N].x].push_back(make_pair(make_pair(dot[i].y,dot[ans[i]+N].y),0));
	}
	multiset<int> post;
	for(int i=1;i<=2*N+1;++i){
		sort(buc[i].begin(),buc[i].end(),cmp);
		for(auto j:buc[i]){
			if(j.se==1){
				if(post.count(j.fi.se))fail;
				post.insert(j.fi.se);
				auto it=post.lower_bound(j.fi.fi);
				if(it==post.end()||(*it)!=j.fi.se)fail;
				if(j.fi.se!=j.fi.fi&&post.count(j.fi.fi))fail;
				post.insert(j.fi.fi);
			}else{
				auto it=post.lower_bound(j.fi.fi);
				post.erase(it);
				it=post.lower_bound(j.fi.fi);
				if(it==post.end()||(*it)!=j.fi.se)fail;
				post.erase(j.fi.se);
			}
		}
	}
	for(int i=1;i<=N;++i)printf("%d\n",ans[i]);
	// fclose(stdin);
	// fclose(stdout);
	return 0;
}

标签:const,Python,ICPC,++,int,lx,fi,include,se
来源: https://www.cnblogs.com/YouthRhythms/p/16411507.html