CF576E Painting Edges

Posted smyjr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF576E Painting Edges相关的知识,希望对你有一定的参考价值。

cf

luogu

水一发经验以防大家都以为我死了 其实也快了

因为不是二分图当且仅当存在奇环,所以考虑对每种颜色维护一个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的主要内容,如果未能解决你的问题,请参考以下文章

CF576E Painting Edges [线段树分治,可撤销并查集]

576E - Painting Edges

CF1198E Rectangle Painting 2

CF1479B Painting the Array

cf 448 C. Painting Fence

题解 CF1242A Tile Painting