UOJ356 【JOI2017春季合宿】Port Facility

暴力就是O(n^2)连边,二分图,这样只有22分。

我们考虑优化建边,我们按照左端点排序,对于一个新加进来的线段,我们向左端点距其最近的和他相交的线段连边,别的相交的我们连同色边,当一个点连了两条同色边我们就把它删掉,复杂度O(nlogn),边数O(n)。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <set>
 7 #define N 2000005
 8 #define inf 1000000000
 9 #define mod 1000000007
10 using namespace std;
11 set <int> s1,s2;
12 set <int> :: iterator it;
13 int n,nxt[N],pre[N],Ans,vis[N],sta[N],top;
14 struct data{int l,r;}d[N];
15 bool cmpl(data a,data b){return a.l<b.l;}
16 int e=1,head[N];
17 struct edge{int v,w,next;}ed[N<<2];
18 void add(int u,int v,int w){ed[e]=(edge){v,w,head[u]};head[u]=e++;}
19 void dfs(int x,int c){
20     vis[x]=c;
21     for(int i=head[x];i;i=ed[i].next){
22         int v=ed[i].v;
23         if(vis[v]!=-1&&vis[v]!=c^ed[i].w){puts("0");exit(0);}
24         if(vis[v]!=-1)continue;
25         dfs(v,c^ed[i].w);
26     }
27 }
28 int main(){
29     scanf("%d",&n);
30     for(int i=1;i<=n;i++)
31         scanf("%d%d",&d[i].l,&d[i].r);
32     sort(d+1,d+n+1,cmpl);
33     s1.insert(-inf);s1.insert(inf);
34     s2.insert(-inf);s2.insert(inf);
35     for(int i=1,x,y;i<=n;i++){
36         x=d[i].l,y=d[i].r;
37         it=s1.upper_bound(y);
38         nxt[y]=*it;it--;pre[y]=*it;
39         if((*it)>x)add(y,*it,1),add(*it,y,1);
40         it=s2.upper_bound(y);it--;
41         for(;(*it)>x;it--){
42             if(pre[*it]>x)add(*it,pre[*it],0),add(pre[*it],*it,0),pre[*it]=-inf;
43             if(nxt[*it]<y)add(*it,nxt[*it],0),add(nxt[*it],*it,0),nxt[*it]=inf;
44             if(pre[*it]==-inf&&nxt[*it]==inf)sta[++top]=*it;
45         }
46         while(top)s2.erase(sta[top--]);
47         s1.insert(y);s2.insert(y);
48     }
49     Ans=1;
50     memset(vis,-1,sizeof vis);
51     for(int i=1;i<=n;i++)if(vis[d[i].r]==-1){
52         dfs(d[i].r,0);
53         Ans=(Ans<<1)%mod;
54     }
55     printf("%d\n",Ans);
56 }
View Code

 

posted @ 2018-07-11 09:38 Ren_Ivan 阅读(...) 评论(...) 编辑 收藏