CF576E Painting Edges
Posted smyjr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF576E Painting Edges相关的知识,希望对你有一定的参考价值。
水一发经验以防大家都以为我死了 其实也快了
因为不是二分图当且仅当存在奇环,所以考虑对每种颜色维护一个lct,表示这种颜色的边的连通情况,注意可能会出现一些成环的边,那就维护这种颜色的,边权为删除时间的最大生成树,每次加入环边,把环上删除时间最小的边先删掉即可.加边只用考虑是否这两点之间的路径长度为奇数即可,并且可以发现维护的生成树,两点路径长度奇偶性不会收到加入环边的影响,所以直接做即可
#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double
using namespace std;
const int N=5e5+10,M=51;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int n,m,l,q,e[N][2],qq[N][2],bq[N],nt[N],ne[N][2],co[N],nc[N],pt;
map<int,int> id[M];
int fa[N*3],ch[N*3][2],sz[N*3],ti[N],mea[N*3];
bool tg[N*3];
bool nrt(int x){return ch[fa[x]][0]==x||ch[fa[x]][1]==x;}
void rev(int x){if(x) swap(ch[x][0],ch[x][1]),tg[x]^=1;}
void psup(int x)
{
sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+(x<=m);
mea[x]=ti[mea[ch[x][0]]]<ti[mea[ch[x][1]]]?mea[ch[x][0]]:mea[ch[x][1]];
if(x<=m) mea[x]=ti[mea[x]]<ti[x]?mea[x]:x;
}
void rot(int x)
{
int y=fa[x],z=fa[y],yy=ch[y][1]==x,w=ch[x][!yy];
if(nrt(y)) ch[z][ch[z][1]==y]=x;
ch[x][!yy]=y,ch[y][yy]=w;
if(w) fa[w]=y;
fa[y]=x,fa[x]=z;
psup(y);
}
void psdn(int x){if(tg[x]) rev(ch[x][0]),rev(ch[x][1]),tg[x]=0;}
void ppush(int x)
{
if(nrt(x)) ppush(fa[x]);
psdn(x);
}
void spl(int x)
{
ppush(x);
while(nrt(x))
{
int y=fa[x],z=fa[y];
if(nrt(y)) ((ch[y][1]==x)^(ch[z][1]==y))?rot(x):rot(y);
rot(x);
}
psup(x);
}
void acs(int x)
{
for(int y=0;x;y=x,x=fa[x])
spl(x),ch[x][1]=y,psup(x);
}
void mkrt(int x){acs(x),spl(x),rev(x);}
int fdrt(int x)
{
acs(x),spl(x),psdn(x);
while(ch[x][0]) x=ch[x][0],psdn(x);
spl(x);
return x;
}
void split(int x,int y){mkrt(x),acs(y),spl(y);}
void link(int x,int y)
{
split(x,y),fa[x]=y;
}
void linke(int i)
{
ne[i][0]=id[nc[i]][e[i][0]],ne[i][1]=id[nc[i]][e[i][1]];
link(ne[i][0],i),link(ne[i][1],i);
}
void cut(int x,int y)
{
split(x,y);
fa[x]=ch[y][0]=0,psup(y);
}
void cute(int i){cut(i,ne[i][0]),cut(i,ne[i][1]),nc[i]=0;}
int main()
{
////ruaaaaaaaaaaaaaaaaaaaaaa
n=rd(),m=rd(),l=rd(),q=rd();
for(int i=1;i<=m;++i) e[i][0]=rd(),e[i][1]=rd();
pt=m;
for(int i=1;i<=q;++i) qq[i][0]=rd(),qq[i][1]=rd();
for(int i=1;i<=m;++i) bq[i]=q+1;
for(int i=q;i;--i) nt[i]=bq[qq[i][0]],bq[qq[i][0]]=i;
ti[0]=1<<30;
for(int i=1;i<=q;++i)
{
int x=qq[i][0],y=qq[i][1];
if(nc[x]) cute(x);
ti[x]=nt[i];
bool fg=0;
if(!id[y].count(e[x][0])) fg=1,id[y][e[x][0]]=++pt;
if(!id[y].count(e[x][1])) fg=1,id[y][e[x][1]]=++pt;
int xx=id[y][e[x][0]],yy=id[y][e[x][1]];
if(!fg)
{
if(fdrt(xx)!=fdrt(yy)) fg=1;
else
{
split(xx,yy);
fg|=sz[yy]&1;
}
}
if(fg)
{
puts("YES");
co[x]=y;
if(fdrt(xx)==fdrt(yy))
{
split(xx,yy);
int ze=mea[yy];
if(ti[x]<=ti[ze]) continue;
cute(ze);
nc[x]=y,linke(x);
}
else nc[x]=y,linke(x);
}
else
{
puts("NO");
if(co[x])
{
xx=id[co[x]][e[x][0]],yy=id[co[x]][e[x][1]];
if(fdrt(xx)==fdrt(yy))
{
split(xx,yy);
int ze=mea[yy];
if(ti[x]<=ti[ze]) continue;
cute(ze);
nc[x]=co[x],linke(x);
}
else nc[x]=co[x],linke(x);
}
}
}
return 0;
}
以上是关于CF576E Painting Edges的主要内容,如果未能解决你的问题,请参考以下文章