bzoj4881 [ Lydsy2017年5月月赛 ] -- 二分图染色+线段树
来源:互联网 发布:手机虚拟试衣软件 编辑:程序博客网 时间:2024/05/29 03:03
以下是Claris的题解:bzoj4881
若线段 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 }
阅读全文
0 0
- bzoj4881 [ Lydsy2017年5月月赛 ] -- 二分图染色+线段树
- bzoj4881: [Lydsy2017年5月月赛]线段游戏
- BZOJ4881 [Lydsy2017年5月月赛]线段游戏
- BZOJ4881: [Lydsy2017年5月月赛]线段游戏
- BZOJ 4881 [Lydsy2017年5月月赛] 二分图染色+线段树
- 4881: [Lydsy2017年5月月赛]线段游戏
- BZOJ 4878([Lydsy2017年5月月赛]挑战NP-Hard-染色问题)
- BZOJ4882: [Lydsy2017年5月月赛]卡常生成树
- bzoj4885: [Lydsy2017年5月月赛]长方体
- BZOJ4885: [Lydsy2017年5月月赛]长方体
- bzoj5049 [Lydsy2017年5月月赛]导航系统
- bzoj 4881: [Lydsy2017年5月月赛]线段游戏 树状数组+set
- bzoj 4880: [Lydsy2017年5月月赛]排名的战争
- bzoj4878: [Lydsy2017年5月月赛]挑战NP-Hard
- bzoj4879: [Lydsy2017年5月月赛]失控的数位板
- BZOJ4884 [Lydsy2017年5月月赛]太空猫
- BZOJ4880 [Lydsy2017年5月月赛]排名的战争
- BZOJ4883 [Lydsy2017年5月月赛]棋盘上的守卫
- bzoj4546 -- 可持久化字典树
- bzoj4712 -- 树链剖分
- SpringMVC用PropertyPlaceholderConfigurer读取配置文件
- Oracle数字函数
- bzoj2588 -- 树链剖分+主席树
- bzoj4881 [ Lydsy2017年5月月赛 ] -- 二分图染色+线段树
- bzoj2165 -- 倍增floyd
- bzoj3626 [ LNOI2014 ] -- 树链剖分
- POJ2104_K-th Number_归并树|二分 ||平方分割的分桶法|二分
- SVN导下来Maven工程就报错 org.apache.ibatis.binding.BindingException
- bzoj1857 [ SCOI2010 ] -- 三分套三分
- WampServer 中Apache配置别名访问
- 三国历史脉络图
- flex布局(4)