bzoj4881 [ Lydsy2017年5月月赛 ] -- 二分图染色+线段树

来源:互联网 发布:手机虚拟试衣软件 编辑:程序博客网 时间:2024/05/29 03:03
以下是Claris的题解:

若线段 i j 相交,那么在它们之间连一条边。若这个图不是二分图,那么无解,否则令cnt 为连通块个数,那么 ans = 2cnt

在二分图染色的过程中,每个点只需要被访问一次。对于当前所在的点 x,它可以一步走到 [1, x) 里 p[i] > p[x] 的所有 i,以及 (x, n] 里 p[j] < p[x] 的所有 j。

用线段树维护所有没走过的点,记录每个区间 p 最小与最大的两个位置。每次贪心取出最大/小的,看看是否满足条件,

若满足则删除该点,然后递归染色,否则终止。
时间复杂度 O(n log n)。

 

代码:

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define N 100010 7 #define M 998244353 8 #define INF 1000000 9 int i,j,k,n,m,p[N],c[2][N<<2],s[2][N<<2],Cnt,f[2];10 bool a[N],v[N];11 inline int Min(int x,int y){return x<y?x:y;}12 inline int Max(int x,int y){return x<y?y:x;}13 inline void Up(int Node){14     c[0][Node]=Min(c[0][Node<<1],c[0][Node<<1|1]);15     s[0][Node]=c[0][Node]==c[0][Node<<1]?s[0][Node<<1]:s[0][Node<<1|1];16     c[1][Node]=Max(c[1][Node<<1],c[1][Node<<1|1]);17     s[1][Node]=c[1][Node]==c[1][Node<<1]?s[1][Node<<1]:s[1][Node<<1|1];18 }19 inline void Update(int Node,int l,int r,int x){20     if(l==r){21         c[0][Node]=INF;22         c[1][Node]=s[0][Node]=s[1][Node]=0;23         return;24     }25     int Mid=l+r>>1;26     if(x<=Mid)Update(Node<<1,l,Mid,x);else Update(Node<<1|1,Mid+1,r,x);27     Up(Node);28 }29 inline int Query(int Node,int l,int r,int L,int R,bool d){30     if(l>=L&&r<=R)return s[d][Node];31     int Mid=l+r>>1;32     if(Mid<L)return Query(Node<<1|1,Mid+1,r,L,R,d);33     if(Mid>=R)return Query(Node<<1,l,Mid,L,R,d);34     int Q1=Query(Node<<1,l,Mid,L,R,d),Q2=Query(Node<<1|1,Mid+1,r,L,R,d);35     if(Q1&&(d^(p[Q1]<p[Q2]?1:0)))return Q1;return Q2;36 }37 inline void Dfs(int x){38     v[x]=1;39     Update(1,1,n,x);40     while(1){41         if(x>1){42             int y=Query(1,1,n,1,x-1,1);43             if(y&&p[y]>p[x]){44                 a[y]=a[x]^1;45                 Dfs(y);46                 continue;47             }48         }49         if(x<n){50             int y=Query(1,1,n,x+1,n,0);51             if(y&&p[y]<p[x]){52                 a[y]=a[x]^1;53                 Dfs(y);54                 continue;55             }56         }57         break;58     }59 }60 inline int Pow(int x,int y){61     if(y==0)return 1;62     int Ans=Pow(x,y>>1);63     Ans=1ll*Ans*Ans%M;64     if(y&1)Ans=1ll*Ans*x%M;65     return Ans;66 }67 inline void Build(int Node,int l,int r){68     if(l==r){69         scanf("%d",&p[l]);70         c[0][Node]=c[1][Node]=p[l];71         s[0][Node]=s[1][Node]=l;72         return;73     }74     int Mid=l+r>>1;75     Build(Node<<1,l,Mid);76     Build(Node<<1|1,Mid+1,r);77     Up(Node);78 }79 int main(){80     scanf("%d",&n);81     Build(1,1,n);82     for(i=1;i<=n;i++)83     if(!v[i])a[i]=1,Dfs(i),Cnt++;84     for(i=1;i<=n;i++)85     if(f[a[i]]>p[i]){puts("0");return 0;}else f[a[i]]=p[i];86     printf("%d\n",Pow(2,Cnt));87     return 0;88 }
bzoj4881

 

阅读全文
0 0