【JOI2017春季合宿】Port Facility
题解
思路和\(NOIP\)双栈排序差不多。
对于两个元素,若\(l_1<l_2<r_1<r_2\)那么它们不能在一个栈里,我们连一条边。
若最后的这张图是二分图,那么答案就是\(2^{联通块个数}\)。
这道题就是要我们优化连边。
我们把所有线段按照左端点排序,然后我们用平衡树按照右端点为关键字维护已经扫描过去的线段。
发现要和当前扫描到的线段连边的是平衡树上\(dfs\)序连续的一段区间。
考虑这个边怎么连。
我们只需要在这个区间的右端点处和这个点连上1的边,中间连0边就行了。
所以我们可以用并查集的思想,只和右端点连边,在维护一个连0边的\(set\),如果一个点和两边都连上0边就删掉它。
代码
#include<bits/stdc++.h>
#define N 2000009
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inf=1e9;
int pre[N],nxt[N],head[N],tot;
int top,st[N];
int n;
int vis[N];
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
inline void MOD(int &x){x=x>=mod?x-mod:x;}
inline ll power(ll x,ll y){
ll ans=1;
while(y){
if(y&1)ans=ans*x%mod;
x=x*x%mod;y>>=1;
}
return ans;
}
struct edge{
int n,to,l;
}e[N*6];
inline void add(int u,int v,int l){
if(!u||!v)return;
// cout<<u<<" "<<v<<" "<<l<<endl;
e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;
e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=l;
}
struct node{
int l,r;
inline bool operator <(const node &b)const{
if(l!=b.l)return l<b.l;
return r<b.r;
}
}a[N];
struct nd{
int pos,id;
inline bool operator <(const nd &b)const{
return pos<b.pos;
}
};
set<nd>s1,s2;
set<nd>::iterator it;
void dfs(int u){
for(int i=head[u];i;i=e[i].n){
int v=e[i].to;
if(vis[v]&&(vis[u]^e[i].l)!=vis[v]){puts("0");exit(0);}
if(!vis[v]){
vis[v]=vis[u]^e[i].l;
dfs(v);
}
}
}
int main(){
n=rd();
for(int i=1;i<=n;++i)a[i].l=rd(),a[i].r=rd();
sort(a+1,a+n+1);
s1.insert(nd{-inf,0});s1.insert(nd{inf,0});
s2.insert(nd{-inf,0});s2.insert(nd{inf,0});
for(int i=1;i<=n;++i){
it=s1.lower_bound(nd{a[i].r,i});
nxt[i]=it->id;
pre[it->id]=0;
it--;
pre[i]=it->id;
nxt[it->id]=0;
if(it->pos>a[i].l)add(i,it->id,1);
it=s2.lower_bound(nd{a[i].r,i});--it;
while(1){
if(it->pos<a[i].l)break;
if(pre[it->id]&&a[pre[it->id]].r>a[i].l){add(it->id,pre[it->id],0);pre[it->id]=0;}
if(nxt[it->id]&&a[nxt[it->id]].r<a[i].r){add(it->id,nxt[it->id],0);nxt[it->id]=0;}
if(!pre[it->id]&&!nxt[it->id])st[++top]=it->id;
it--;
}
for(int j=1;j<=top;++j)s2.erase(nd{a[st[j]].r,st[j]});
top=0;
s1.insert(nd{a[i].r,i});
s2.insert(nd{a[i].r,i});
}
int ans=1;
for(int i=1;i<=n;++i)if(!vis[i]){
vis[i]=2;
dfs(i);
MOD(ans=ans+ans);
}
printf("%d\n",ans);
return 0;
}