CF1137F Matches Are Not a Child's Play 题解
阅读原文时间:2023年07月08日阅读:3

以最后被删去的点为根,这样子不会存在从父亲然后删掉某个点,儿子的删除顺序一定比父亲前。

记每个点子树中的最大值为 \(f_x\),那么一个点的排名,首先就需要加上 \(<f_x\) 的所有值,记对应 \(f_x\) 的点为 \(y\),那么 \(y\) 一定会一路上来删掉 \(x\)。

所以一个点排名就是 \(<f_x\) 的所有值,再加上 \(x,y\) 之间的距离。

考虑如何维护修改,设上一个根是 \(rt\),新根是 \(x\),那么等价于一次换根,需要将 \(x\) 到 \(rt\) 这条路径 cover 上 \(p_{rt}\),同时改掉 \(x\) 的值。

可以使用 ODT + 树剖维护。

Code

const int N=2e5+5;
int n,m;
vi G[N];
int dep[N],siz[N],top[N],son[N],dfn[N],fat[N],dfc,p[N*2],rp[N*2];
void dfs1(int u,int fa) {
    dep[u]=dep[fa]+1,siz[u]=1,fat[u]=fa;
    for(int v:G[u]) if(v!=fa) {
        dfs1(v,u),siz[u]+=siz[v];
        p[u]=max(p[u],p[v]);
        if(siz[son[u]]<siz[v]) son[u]=v;
    }
}
void dfs2(int u,int tp,int fa) {
    top[u]=tp,dfn[u]=++dfc;
    if(son[u]==0) return;
    dfs2(son[u],tp,u);
    for(int v:G[u]) if(v!=fa&&v!=son[u]) dfs2(v,v,u);
}
int bit[2*N];
void add(int x,int v) { for(;x<=n+m;x+=(x&-x)) bit[x]+=v; }
int ask(int x) { int ret=0; for(;x;x-=(x&-x)) ret+=bit[x]; return ret; }
struct node {
    int l,r,v;
    node() {}
    node(int L,int R,int V) { l=L,r=R,v=V; }
    bool operator < (const node &a) const { return l<a.l; }
};
set<node> odt;
auto spilt(int p) {
    auto it=odt.lower_bound(node(p,-1,0));
    if(it!=odt.end()&&it->l==p) return it;
    --it;
    int l=it->l,r=it->r,v=it->v;
    odt.erase(it),odt.insert(node(l,p-1,v));
    return odt.insert(node(p,r,v)).fi;
}
void cover(int l,int r,int v) {
    auto itr=spilt(r+1),itl=spilt(l);
    for(auto it=itl;it!=itr;it=odt.erase(it)) add(it->v,-((it->r)-(it->l)+1));
    add(v,r-l+1),odt.insert(node(l,r,v));
}
void update(int u,int v,int w) {
    while(top[u]!=top[v]) {
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        cover(dfn[top[u]],dfn[u],w),u=fat[top[u]];
    }
    if(dep[u]>dep[v]) swap(u,v);
    cover(dfn[u],dfn[v],w);
}
int lca(int u,int v) {
    while(top[u]!=top[v]) {
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        u=fat[top[u]];
    }
    return dep[u]<dep[v]?u:v;
}
int dist(int u,int v) { return dep[u]+dep[v]-2*dep[lca(u,v)]+1; }
int query(int x) {
    auto pos=odt.upper_bound(node(dfn[x],-1,0));
    int val=prev(pos)->v;
    return ask(val-1)+dist(x,rp[val]);
}
int main() {
    n=read(),m=read();
    FOR(i,1,n-1) {
        int x=read(),y=read();
        G[x].pb(y),G[y].pb(x);
    }
    FOR(i,1,n) p[i]=rp[i]=i;
    int rt=n,mx=n;
    dfs1(n,0),dfs2(n,n,0);
    FOR(i,1,n) add(p[i],1),odt.insert(node(dfn[i],dfn[i],p[i]));
    FOR(i,1,m) {
        string ch; cin>>ch;
        int u=read();
        if(ch[0]=='1') {
            if(u!=rt) update(rt,u,mx);
            ++mx,cover(dfn[u],dfn[u],mx),rp[mx]=rt=u;
        }
        else if(ch[0]=='2') printf("%d\n",query(u));
        else { int v=read(); printf("%d\n",query(u)>query(v)?v:u);}
    }
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章