BZOJ 3514 Codechef MARCH14 GERALD07加强版

来源:互联网 发布:淘宝货源外国 编辑:程序博客网 时间:2024/04/30 15:31

Description

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

题解
LCT神题==
主席树只是辅助==然而并不会太敲。
这题神YY==水平太烂所以还是看了wulala的题解==
首先观察对答案的贡献。
当一条边和后面的边形成了环,那么它对答案的贡献是0。
不然就是-1咯==
所以每次加入一条边就把它能形成的环的最早的弹掉,弹不了就弹0。
LCT一发。
然后答案就是n剪掉l~r中弹出的边中小于l的个数。
主席树一发。
发现自己主席树简直弱渣。
还有LCT中rotateTM竟然敲错了==调了良久没调出来==

#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int M=4e5+5;int qid[M],st[M];struct LCT{    int tr[M][2],fa[M],mi[M],q[M],rev[M],val[M],top;    inline bool is_root(int x){        return tr[fa[x]][0]!=x&&tr[fa[x]][1]!=x;    }    inline void up(int x){        mi[x]=x;        if(val[mi[tr[x][0]]]<val[mi[x]])mi[x]=mi[tr[x][0]];        if(val[mi[tr[x][1]]]<val[mi[x]])mi[x]=mi[tr[x][1]];    }    inline void rotate(int x){        int y=fa[x],z=fa[y],r=tr[y][0]==x,l=r^1;        if(!is_root(y)){            if(tr[z][0]==y)tr[z][0]=x;            else tr[z][1]=x;        }        fa[x]=z,fa[y]=x,fa[tr[x][r]]=y;        tr[y][l]=tr[x][r],tr[x][r]=y;        up(y);    }    inline void down(int x){        if(!rev[x])return ;        rev[tr[x][0]]^=1,rev[tr[x][1]]^=1;        rev[x]=0;swap(tr[x][0],tr[x][1]);    }    void Splay(int x){        q[++top]=x;        for(int i=x;!is_root(i);i=fa[i])q[++top]=fa[i];        for(;top;)down(q[top--]);        for(;!is_root(x);){            int y=fa[x],z=fa[y];            if(!is_root(y)){                if(tr[z][0]==y^tr[y][0]==x)rotate(x);                else rotate(y);            }            rotate(x);        }        up(x);    }    inline void Access(int x){        for(int t=0;x;t=x,x=fa[x])            Splay(x),tr[x][1]=t,up(x);    }    inline void Make_root(int x){        Access(x);Splay(x);rev[x]^=1;    }    inline void Cut(int x,int y){        Make_root(x);Access(y);Splay(y);        fa[x]=tr[y][0]=0;    }    inline int query(int x,int y){        Make_root(x),Access(y),Splay(y);        return mi[y];    }    inline void Link(int x,int y){        Make_root(x);fa[x]=y;    }    inline int find(int x){        Access(x);Splay(x);        for(;tr[x][0];)x=tr[x][0];        return x;    }}T;struct Pre_Tree{    int tot,ls[M*20],rs[M*20],cnt[M*20];    inline Pre_Tree(){tot=0;}    void Insert(int l,int r,int ot,int &tid,const int x){        cnt[tid=++tot]=cnt[ot]+1;        if(l==r)return;        ls[tid]=ls[ot],rs[tid]=rs[ot];        int mid=l+r>>1;        if(x<=mid)Insert(l,mid,ls[ot],ls[tid],x);        else Insert(mid+1,r,rs[ot],rs[tid],x);    }    int query(int lt,int rt,int l,int r,int k){        if(r==k)return cnt[rt]-cnt[lt];        int mid=l+r>>1;        if(k<=mid)return query(ls[lt],ls[rt],l,mid,k);        return query(rs[lt],rs[rt],mid+1,r,k)+cnt[ls[rt]]-cnt[ls[lt]];    }}PT;inline void rd(int &a){    a=0;char c;    while(c=getchar(),!isdigit(c));    do a=a*10+(c^48);        while(c=getchar(),isdigit(c));}int main(){    int n,m,q,t,u,v;    rd(n),rd(m),rd(q),rd(t);    int tot=n;    for(int i=0;i<=n;++i)T.mi[i]=i,T.val[i]=1<<30;    for(int i=1;i<=m;++i){        rd(u),rd(v);        if(u==v){st[i]=i;continue;}        if(T.find(u)==T.find(v)){            int t=T.query(u,v);            st[i]=T.val[t];            T.Cut(u,t),T.Cut(v,t);        }        T.mi[++tot]=tot,T.val[tot]=i;        T.Link(u,tot),T.Link(v,tot);    }    for(int i=1;i<=m;++i)        PT.Insert(0,m,qid[i-1],qid[i],st[i]);    for(int lastans=0;q--;){        rd(u),rd(v);        if(t)u^=lastans,v^=lastans;        printf("%d\n",lastans=n-PT.query(qid[u-1],qid[v],0,m,u-1));    }    return 0;}
0 0
原创粉丝点击