zoukankan      html  css  js  c++  java
  • [bzoj3514]Codechef MARCH14 GERALD07加强版

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。 n,m<=200000 强制在线

    如果我能知道每条边在什么时候有贡献,我就能算出答案,所以考虑找到最迟的和它冲突的边。

    找的方法可以以编号为边权,用一个LCT维护最大生成树,每次如果冲突就找到最小的边替换,而它起作用的时间段就是这条边之后。

    算答案明显可以主席树,所以这道题就解决啦。

    #include<iostream>
    #include<cstdio>
    #define MN 200000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,m,k,type,last,fa[MN+5],c[MN+5][2],f[MN+5],p[MN+5],q[MN+5],top,mx[MN+5],L[MN+5],R[MN+5],rt[MN+5],cnt=0;
    struct node{int l,r,x;}T[MN*25];
    bool rev[MN+5];
    struct edge{int from,to;}e[MN+5];
    
    inline bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
    inline void update(int x)
    {
        int l=c[x][0],r=c[x][1];
        L[x]=f[x];R[x]=p[x];
        mx[x]=max(p[x],f[x]);
        if(l)  L[x]=L[l],mx[x]=max(mx[x],mx[l]);
        if(r)  R[x]=R[r],mx[x]=max(mx[x],mx[r]);
    }
    void pushdown(int x)
    {
        if(x&&rev[x])
        {
            int l=c[x][0],r=c[x][1];
            rev[l]^=1;rev[r]^=1;rev[x]^=1;
            swap(f[l],p[l]);swap(L[l],R[l]);
            swap(f[r],p[r]);swap(L[r],R[r]);
            swap(c[x][0],c[x][1]);
        }
    }
    
    void rotate(int x)
    {
        int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
        if(!isroot(y)) c[z][c[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        update(y);update(x);
    }
    
    void splay(int x)
    {
        q[top=1]=x;
        for(int t=fa[x];t;t=fa[t]) q[++top]=t;
        for(;top;--top) pushdown(q[top]);
        for(;!isroot(x);rotate(x))
            if(!isroot(fa[x])) rotate((c[fa[fa[x]]][1]==fa[x]^c[fa[x]][1]==x)?x:fa[x]);
    }
    
    void access(int x)
    {
        for(int y=0;x;x=fa[y=x])
            splay(x),c[x][1]=y,p[x]=L[y],update(x); 
    }
    
    
    void link(int x,int y,int z)
    {
        access(x);splay(x);rev[x]^=1;swap(f[x],p[x]);swap(L[x],R[x]); 
        access(y);c[y][1]=x;fa[x]=y;f[x]=p[y]=z;
        update(x);update(y);
    }
    
    void cut(int x,int y)
    {
        access(x);splay(x);rev[x]^=1;swap(f[x],p[x]);swap(L[x],R[x]);
        access(y);splay(y);c[y][0]=fa[x]=f[y]=p[x]=0;
        update(x);update(y);
    }
    
    void ins(int x,int nx,int k)
    {
        int l=0,r=m,mid;
        while(l<r)
        {
            mid=l+r>>1;
            if(k<=mid)
            {
                T[nx].r=T[x].r;T[nx].l=++cnt;
                x=T[x].l;nx=T[nx].l;r=mid;
            }
            else
            {
                T[nx].l=T[x].l;T[nx].r=++cnt;
                x=T[x].r;nx=T[nx].r;l=mid+1;
            }
            T[nx].x=T[x].x+1;
        }
    }
    
    int query(int x,int nx,int k)
    {
        int sum=0,l=0,r=m,mid;
        while(l<r)
        {
            mid=l+r>>1;
            if(k>mid) sum+=T[T[nx].l].x-T[T[x].l].x,x=T[x].r,nx=T[nx].r,l=mid+1;
            else x=T[x].l,nx=T[nx].l,r=mid;
        }
        return sum+T[nx].x-T[x].x;
    }
    
    int main()
    {
        n=read();m=read();k=read();type=read();
        for(int i=1;i<=m;i++) e[i].from=read(),e[i].to=read();
        for(int i=1;i<=m;i++)
        {
            int res=0,x=e[i].from,y=e[i].to;
            if(x!=y)
            {
                access(x);splay(x);rev[x]^=1;swap(f[x],p[x]);swap(L[x],R[x]);
                access(y);splay(y);
                if(!isroot(x)) res=mx[y],cut(e[m+1-res].from,e[m+1-res].to);
                link(x,y,m+1-i);ins(rt[i-1],rt[i]=++cnt,res?m+1-res:0);
            } 
            else rt[i]=rt[i-1];
        }    
        for(int i=1;i<=k;i++)
        {
            int l=read()^(last*type),r=read()^(last*type);
            printf("%d
    ",last=n-query(rt[l-1],rt[r],l-1));
        }
        return 0;
    }
  • 相关阅读:
    【模板】扩展中国剩余定理(EXCRT)
    战略游戏(树形DP)
    二叉苹果树(树形DP)
    货车运输(最大生成树,LCA)
    [CQOI2016]密钥破解
    Pollard-Rho算法andMiller_Rabin算法
    [TJOI2009]猜数字(中国剩余定理)
    中国剩余定理(学习笔记)
    线段树 Segment Tree
    辗转相除法
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj3514.html
Copyright © 2011-2022 走看看