【JOI2017春季合宿】Port Facility

http://uoj.ac/problem/356

题解

思路和\(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;
}
posted @ 2019-07-03 11:44  comld  阅读(315)  评论(0编辑  收藏  举报