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 }
人生如梦亦如幻 朝如晨露暮如霞。