CF414E Mashmokh's Designed Problem(ETT+二分)

版权声明:转载附上原文地址即可~欢迎各位神犇来虐~ https://blog.csdn.net/Icefox_zhx/article/details/80691076

ETT维护欧拉序。每个点维护它的深度,出点入点基本无异。
第一个操作求个lca就好了qaq,x,y的lca就是(in[x],out[y])中深度最小的点的父亲。
第二个操作,x的kth祖先,就是[1,in[x]]中最靠右的深度为dep[x]-k的点。
第三个操作,我们注意到欧拉序上一段连续的区间的深度是连续的,于是我们可以维护每个区间的深度最小/最大值,然后二分来找到深度k的最后一个出现位置,直接在splay上二分即可。
其他的就是普通ETT的操作了。
复杂度O(qlogn)
不用加哨兵…坑我半天不会把哨兵放进去。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,m,in[N],out[N],dfn=0,fa[N<<1],c[N<<1][2],dep[N<<1],mn[N<<1],mx[N<<1],id[N<<1],rt=0,tag[N<<1],sz[N<<1],q[N<<1];
vector<int>Son[N];
inline void dfs(int x,int dept){
    in[x]=++dfn;dep[dfn]=dept;id[dfn]=x;
    for(int i=0;i<Son[x].size();++i) dfs(Son[x][i],dept+1);
    out[x]=++dfn;dep[dfn]=dept;id[dfn]=x;
}
inline void update(int p){
    int l=c[p][0],r=c[p][1];
    sz[p]=sz[l]+sz[r]+1;
    mx[p]=mn[p]=dep[p];
    mx[p]=max(mx[p],max(mx[l],mx[r]));
    mn[p]=min(mn[p],min(mn[l],mn[r]));
}
inline void doadd(int p,int val){
    tag[p]+=val;dep[p]+=val;mn[p]+=val;mx[p]+=val;
}
inline void pushdown(int p){
    if(!tag[p]) return;int l=c[p][0],r=c[p][1];
    if(l) doadd(l,tag[p]);if(r) doadd(r,tag[p]);tag[p]=0;
}
inline void build(int &p,int l,int r){
    int mid=l+r>>1;p=mid;
    if(l<mid) build(c[p][0],l,mid-1),fa[c[p][0]]=p;
    if(r>mid) build(c[p][1],mid+1,r),fa[c[p][1]]=p;update(p);
}
inline void rotate(int x,int &k){
    int y=fa[x],z=fa[y],l=x==c[y][1],r=l^1;
    if(y==k) k=x;
    else c[z][y==c[z][1]]=x;
    fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
    c[y][l]=c[x][r];c[x][r]=y;update(y);update(x);
}
inline void splay(int x,int &k){
    int top=0;q[++top]=x;
    for(int xx=x;xx!=k;xx=fa[xx]) q[++top]=fa[xx];
    while(top) pushdown(q[top--]);
    while(x!=k){
        int y=fa[x],z=fa[y];
        if(y!=k){
            if(x==c[y][1]^y==c[z][1]) rotate(x,k);
            else rotate(y,k);
        }rotate(x,k);
    }
}
inline int findk(int p,int x){
    int r=c[p][1];pushdown(p);
    if(mn[r]<=x&&mx[r]>=x) return findk(r,x);
    if(dep[p]==x) return id[p];
    return findk(c[p][0],x);
}
inline int split(int x,int y){
    splay(x,rt);splay(y,c[x][1]);return c[y][0];
}
inline int getpre(int x){
    splay(x,rt);int res=c[x][0];
    while(c[res][1]) res=c[res][1];
    return res;
}
inline int getsucc(int x){
    splay(x,rt);int res=c[x][1];
    while(c[res][0]) res=c[res][0];
    return res;
}
inline int del1(int x,int y){
    int xx=getpre(x),yy=getsucc(y);
    x=split(xx,yy);y=fa[x];c[y][0]=fa[x]=0;update(y);update(fa[y]);return x;
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();m=read();mx[0]=0;mn[0]=inf;
    for(int i=1;i<=n;++i){
        int owo=read();
        while(owo--) Son[i].push_back(read());
    }dfs(1,0);build(rt,1,n<<1);
    while(m--){
        int op=read(),x=read();
        if(op==3){
            printf("%d\n",findk(rt,x));continue;
        }int y=read();
        if(op==1){
            splay(in[x],rt);int xx=sz[c[in[x]][0]]+1,res=dep[in[x]];
            splay(in[y],rt);int yy=sz[c[in[y]][0]]+1;res+=dep[in[y]];
            if(xx>yy) swap(x,y);x=split(in[x],out[y]);res-=2*(mn[x]-1);
            printf("%d\n",res);continue;
        }splay(in[x],rt);int val=y-1;y=findk(c[rt][0],dep[in[x]]-y);
        x=del1(in[x],out[x]);doadd(x,-val);int xx=getpre(out[y]);
        splay(xx,rt);splay(out[y],c[rt][1]);c[out[y]][0]=x;fa[x]=out[y];
        update(out[y]);update(rt);
    }return 0;
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页