【ZJOI2016】大森林

这题理论上可以用ETT,但是用LCT建虚点可以解决这个问题。

对于最晚的操作1建立一个虚点,然后把操作0挂上去。

#include<bits/stdc++.h>
const int N=4e5+5;
using namespace std;
struct Link_Cut_Tree{
    int size[N],w[N],c[N][2],fa[N],cnt,rev[N],q[N];
    inline void newnode(int x){++cnt;size[cnt]=w[cnt]=x;}
    inline bool isroot(int x){return (c[fa[x]][1]!=x&&c[fa[x]][0]!=x)||!x;}
    inline void pushup(int x){size[x]=size[c[x][0]]+size[c[x][1]]+w[x];}
    inline void pushdown(int x){
        int l=c[x][0],r=c[x][1];
        if(rev[x]){
            rev[l]^=1;rev[r]^=1;rev[x]^=1;
            swap(c[x][0],c[x][1]);
        }
    }
    inline void rotate(int x){
        int y=fa[x],z=fa[y],l,r;
        if(c[y][0]==x)l=0;else l=1;r=l^1;
        if(!isroot(y)){if(c[z][0]==y)c[z][0]=x;else c[z][1]=x;}
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        pushup(y);pushup(x);
    }
    inline void splay(int x){
        int top=1;q[top]=x;
        for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
        for(int i=top;i;i--)pushdown(q[i]);
        while(!isroot(x)){
            int y=fa[x],z=fa[y];
            if(!isroot(y)){
                if((c[y][0]==x)^(c[z][0]==y))rotate(x);
                else rotate(y);
            }rotate(x);
        }
        pushup(x);
    }
    inline int access(int x){int t=0;for(;x;t=x,x=fa[x])splay(x),c[x][1]=t,pushup(x);return t;}
    inline void cut(int x){access(x),splay(x),fa[c[x][0]]=0,c[x][0]=0;pushup(x);}
    inline void link(int x,int y){splay(x);fa[x]=y;}
}T;
struct Opt{
    int pos,opt,x,y;
    Opt(int pos=0,int opt=0,int x=0,int y=0):pos(pos),opt(opt),x(x),y(y){}
}a[N];
bool cmp(Opt a,Opt b){return a.pos==b.pos?a.opt<b.opt:a.pos<b.pos;}
int n,m,op[N],ed[N],b[N],tot=1,ans[N],vis[N],top;
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
int main(){
    n=read();m=read();int now=0;
    T.newnode(1);T.newnode(0);T.link(2,1);now=2;
    b[1]=1;op[1]=1;ed[1]=n;
    for(int i=1;i<=m;i++){
        int opt=read(),l=read(),r=read();
        if(opt==0){
            ++tot;T.newnode(1);
            b[tot]=T.cnt;op[tot]=l;ed[tot]=r;
            a[++top]=Opt(1,i-m,T.cnt,now);
        }
        else if(opt==1){
            int k=read();l=max(op[k],l);r=min(r,ed[k]);
            if(l<=r){
                T.newnode(0);T.link(T.cnt,now);
                a[++top]=Opt(l,i-m,T.cnt,b[k]);
                a[++top]=Opt(r+1,i-m,T.cnt,now);
                now=T.cnt;
            }
        }
        else{
            int k=read();vis[i]=1;
            a[++top]=Opt(l,i,b[r],b[k]);
        }
    }
    sort(a+1,a+top+1,cmp);int k=1,t=0;
    for(int i=1;i<=n;i++){
        for(;a[k].pos==i;k++){
            if((t=a[k].opt)>0){
                int x=a[k].x,y=a[k].y;
                T.access(x);T.splay(x);ans[t]+=T.size[x];
                int lca=T.access(y);T.splay(y);ans[t]+=T.size[y];
                T.access(lca);T.splay(lca);ans[t]-=T.size[lca]*2;
            }else{T.cut(a[k].x);T.link(a[k].x,a[k].y);}
        }
    }
    for(int i=1;i<=m;i++)if(vis[i])printf("%d\n",ans[i]);
}

 

posted @ 2017-08-08 22:42  zcysky  阅读(617)  评论(0编辑  收藏  举报