【AtCoder Regular Contest 076 E】Connected?
括号匹配。
题目大意:
给定一个矩形区域上的若干对点,要求用曲线连接每一对点,并满足:
- 曲线不相交。
- 曲线不超出矩形的边界。
问是否存在合法方案。
题解:
发现只有两个端点都在边界上的点对才会对答案产生影响,而一个端点在中间的情况,必定可以通过曲折来满足条件。
我们将边界看成一个环,那么一个点对会将一段区间分成两个部分。如果一个点对的两个端点已经在不同部分了,那么就没有合法方案了。
我们可以使用括号匹配来完成。将第一个端点看成左括号,第二个端点看成右括号,则这对括号将一个段分成括号内和括号外两部分。
如果最后括号匹配合法,则有方案,否则无方案。
Code:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N=1e5+6;
int n,sta[N],top,R,C;
bool vis[N];
vector<pair<int,int> >v[4];
inline bool chk(int x,int y){return x==0||x==R||y==0||y==C;}
void push(int r,int c,int id){
if(!r)v[0].emplace_back(c,id);else if(c==C)v[1].emplace_back(r,id);else
if(r==R)v[2].emplace_back(C-c,id);else v[3].emplace_back(R-r,id);
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>R>>C>>n;
for(int i=1;i<=n;++i){
int r1,c1,r2,c2;
cin>>r1>>c1>>r2>>c2;
if(chk(r1,c1)&&chk(r2,c2))push(r1,c1,i),push(r2,c2,i);
}
for(int i=0;i<4;++i){
sort(v[i].begin(),v[i].end());
for(auto x:v[i]){
int id=x.second;
if(!vis[id])sta[++top]=id,vis[id]=1;else if(!top||sta[top]!=id){cout<<"NO\n";return 0;}else --top;
}
}
cout<<"YES\n";
return 0;
}