2018.08.27【模板】树链剖分换根(模板)

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/82119758

描述

给定一棵大小为 n 的有根点权树,支持以下操作:
• 换根
• 修改点权
• 查询子树最小值

输入

第一行两个整数 n, Q ,分别表示树的大小和操作数。
接下来n行,每行两个整数f,v,第i+1行的两个数表示点i的父亲和点i的权。保证f < i。如 果f = 0,那么i为根。输入数据保证只有i = 1时,f = 0。
接下来 m 行,为以下格式中的一种:
• V x y表示把点x的权改为y
• E x 表示把有根树的根改为点 x
• Q x 表示查询点 x 的子树最小值

输出

对于每个 Q ,输出子树最小值。

样例输入

3 7
0 1
1 2
1 3
Q 1
V 1 6
Q 1
V 2 5
Q 1
V 3 4
Q 1

样例输出

1
2
3
4

提示

对于 100% 的数据:n, Q ≤ 10^5。

标签

Leo

康复训练ing。。。
先做了一道换根树剖的板子,调了很久发现lca写错了也是很感动。。。
代码:

#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define N 100005
using namespace std;
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
    return ans;
}
inline void write(int x){
    if(x>9)write(x/10);
    putchar((x%10)^48);
}
int n,q,fa[N],first[N],top[N],dep[N],hson[N],siz[N],num[N],pred[N],a[N],rt,cnt=0,tot=0;
struct edge{int next,v;}e[N<<1];
struct node{int l,r,mn;}T[N<<2];
inline void dfs1(int p){
    siz[p]=1,hson[p]=0;
    for(int i=first[p];i;i=e[i].next){
        int v=e[i].v;
        if(v==fa[p])continue;
        fa[v]=p,dep[v]=dep[p]+1,dfs1(v),siz[p]+=siz[v];
        if(siz[v]>siz[hson[p]])hson[p]=v;
    }
}
inline void dfs2(int p,int tp){
    top[p]=tp,num[p]=++tot,pred[tot]=p;
    if(hson[p])dfs2(hson[p],tp);
    for(int i=first[p];i;i=e[i].next){
        int v=e[i].v;
        if(v!=fa[p]&&v!=hson[p])dfs2(v,v);
    }
}
inline int min(int a,int b){return a<b?a:b;}
inline void pushup(int p){T[p].mn=min(T[lc].mn,T[rc].mn);}
inline void build(int p,int l,int r){
    T[p].l=l,T[p].r=r;
    if(l==r){T[p].mn=a[pred[l]];return;}
    build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int k,int v){
    if(T[p].l==T[p].r){T[p].mn=v;return;}
    if(k<=mid)update(lc,k,v);
    else update(rc,k,v);
    pushup(p);
}
inline int query(int p,int ql,int qr){
    if(ql>T[p].r||qr<T[p].l)return 1e9;
    if(ql<=T[p].l&&T[p].r<=qr)return T[p].mn;
    if(qr<=mid)return query(lc,ql,qr);
    if(ql>mid)return query(rc,ql,qr);
    return min(query(lc,ql,mid),query(rc,mid+1,qr));
}
inline int lca(int x,int y){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        x=fa[top[x]];
    }
    return dep[x]<dep[y]?x:y;
}
inline int fid(int x,int y){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        if(fa[top[x]]==y)return top[x];
        x=fa[top[x]];
    }
    if(dep[x]<dep[y])swap(x,y);
    return hson[y];
}
inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;}
int main(){
    int size=40<<20;
    __asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));
    n=read(),q=read(),rt=1;
    for(int i=1;i<=n;++i){
        int pa=read();
        a[i]=read();
        if(i!=1)add(pa,i);
    }
    dfs1(1),dfs2(1,1),build(1,1,n);
    while(q--){
        char s[3];
        scanf("%s",s);
        if(s[0]=='Q'){
            int p=read();
            if(rt==p)write(T[1].mn);
            else{
                int LCA=lca(rt,p);
                if(LCA!=p)write(query(1,num[p],num[p]+siz[p]-1));
                else{int s=fid(p,rt);write(min(query(1,1,num[s]-1),query(1,num[s]+siz[s],n)));}
            }
            puts("");
        }
        else if(s[0]=='E')rt=read();
        else{int v=read(),x=read();update(1,num[v],x);}
    }
    exit(0);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/82119758