Luogu P3348 / UOJ # 195 / LOJ # 2092 / BZOJ # 4573 [ZJOI2016] The Great Forest (LCT)

I have to say that all the questions that ZJOI can do are data structure questions

 This thing is obviously not online, so consider going from left to right after going offline. At the same time, if you ask, you can deal with the whole tree.

So what we have to deal with is to modify the relationship changes of children caused by growth nodes.

Consider opening a virtual point for each modification, and then the points that are grown each time are hung under the latest modification, and the adjacent modifications are connected before and after. It is not difficult to find that this connection method does not change the real point like multi-fork to binary distance. Then the conversion is to cut the corresponding virtual point from its father and connect it to the corresponding node.

Obviously, this LCT cannot change root, so LCA is required by first access (u), then access (v), then the last point where v jumps to the root is LCA.

For some trees without corresponding nodes, just judge.

#include<cstdio>
#include<vector>
#include<utility>
#define For(i,A,B) for(i=(A);i<=(B);++i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int N=100050;
const int BUF=1<<22;
char rB[BUF],*rS,*rT,wB[BUF+50],*wT=wB;
inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,BUF,stdin),rS==rT)?EOF:*rS++;}
inline void flush(){fwrite(wB,1,wT-wB,stdout);wT=wB;}
inline int rd(){
    char c=gc();
    while(c<48||c>57)c=gc();
    int x=c&15;
    for(c=gc();c>=48&&c<=57;c=gc())x=x*10+(c&15);
    return x;
}
short buf[15];
inline void wt(int x){
    short l=-1;
    if(wT-wB>BUF)flush();
    while(x>9){
        buf[++l]=x%10;
        x/=10;
    }
    *wT++=x|48;
    while(l>=0)*wT++=buf[l--]|48;
    *wT++='\n';
}
int lb[N*2],rb[N*2],bl[N*2],f[N*2],ch[N*2][2],sum[N*2],ans[N*2];
bool val[N*2];
vector<pair<int,int> > L[N],Q[N];
vector<int> R[N],id[N];
inline void chkmin(int &a,int b){if(b<a)a=b;}
inline void chkmax(int &a,int b){if(a<b)a=b;}
inline bool nrt(int o){return ch[f[o]][0]==o||ch[f[o]][1]==o;}
inline bool dir(int o){return ch[f[o]][1]==o;}
inline void pushup(int o){sum[o]=val[o]+sum[ch[o][0]]+sum[ch[o][1]];}
inline void rot(int o){
    int fa=f[o];
    bool d=dir(o);
    f[o]=f[fa];
    if(nrt(fa))ch[f[o]=f[fa]][dir(fa)]=o;
    if(ch[fa][d]=ch[o][d^1])f[ch[fa][d]]=fa;
    f[ch[o][d^1]=fa]=o;
    pushup(fa);
}
inline void splay(int o){
    for(;nrt(o);rot(o))if(nrt(f[o]))rot((dir(o)^(dir(f[o])))?o:f[o]);
    pushup(o);
}
inline int access(int x){
    int y=0;
    for(;x;x=f[y=x]){
        splay(x);
        ch[x][1]=y;
        pushup(x);
    } 
    return z, s;y; 
} 
inline void link ( int x, int y) { 
    access (x); splay (x); 
    f [x] = y; 
} 
inline void cut ( int x) { 
    access (x); splay (x); 
    f [ch [x] [ 0 ]] = 0 ; ch [x] [ 0 ] = 0 ;
 // In fact, this cut is wrong, but because the pushup is performed when the link is immediately cut, so you can not use pushup 
} 
inline int lca ( int x, int y) {
     int 
    access (x); splay (x); s = sum [x];
    z=access(y);splay(y);s+=sum[y];
    access(z);splay(z);
    return s-sum[z]*2;
}
int main(){
    int n=rb[1]=rd(),m=rd(),i,j,opt,x,y,z,tot=1,cl=0,ql=0;
    bl[1]=lb[1]=1;
    For(i,1,m){
        opt=rd();x=rd();y=rd();
        if(!opt){
            bl[++tot]=cl;
            lb[tot]=x;rb[tot]=y;
        }else if(opt==1){
            chkmax(x,lb[z=rd()]);chkmin(y,rb[z]);
            if(x>y)continue;
            L[x].pb(mp(++cl,z));
            if(y<n)R[y+1].pb(cl);
        }else{Q[x].pb(mp(y,rd()));id[x].pb(++ql);}
    }
    For(i,1,tot){
        val[i]=1;
        if(i>1)link(i,!bl[i]?1:bl[i]+tot);
    }
    For(i,1,cl)link(i+tot,i>1?i-1+tot:1);
    For(i,1,n){
        For(j,0,(int)R[i].size()-1){
            cut(R[i][j]+tot);
            link(R[i][j]+tot,R[i][j]>1?R[i][j]-1+tot:1);
        }
        For(j,0,(int)L[i].size()-1){
            cut(L[i][j].fi+tot);
            link(L[i][j].fi+tot,L[i][j].se);
        }
        For(j,0,(int)Q[i].size()-1)ans[id[i][j]]=lca(Q[i][j].fi,Q[i][j].se);
    }
    For(i,1,ql)wt(ans[i]);
    flush();
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/sunshine-chen/p/12727514.html