luoguP4092 [HEOI2016/TJOI2016]树

树链剖分的水题。线段树维护区间最接近值就ok啦。

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
int size[maxn],top[maxn],f[maxn],pos[maxn],dep[maxn],head[maxn];
int sz=0,cnt=0,root=1;
struct list{
    int l,r,sum;
}tree[maxn*4];
struct edge{
    int to,next;
}e[maxn*2];
void add_edge(int s,int t){
    e[++cnt].next=head[s];e[cnt].to=t;head[s]=cnt;
    e[++cnt].next=head[t];e[cnt].to=s;head[t]=cnt;
}
void build(int k,int l,int r){
    tree[k].l=l;tree[k].r=r;
    if(l==r)return ;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
}
void dfs1(int u){
    size[u]=1;
    for(int i=head[u];i;i=e[i].next){
        if(f[u]!=e[i].to){
            dep[e[i].to]=dep[u]+1;
            f[e[i].to]=u;
            dfs1(e[i].to);
            size[u]+=size[e[i].to];
        }
    }
}
void dfs2(int u,int ance){
    pos[u]=++sz;
    top[u]=ance;
    int k=0;
    for(int i=head[u];i;i=e[i].next){
        if(f[u]!=e[i].to&&size[k]<size[e[i].to]){
            k=e[i].to;
        }
    }
    if(k==0)return ;
    dfs2(k,ance);
    for(int i=head[u];i;i=e[i].next){
        if(f[u]!=e[i].to&&e[i].to!=k){
            dfs2(e[i].to,e[i].to);
        }
    }
}

//线段树
void pushup(int k){
    int l=tree[k].l,r=tree[k].r;
    if(tree[k<<1|1].sum)tree[k].sum=tree[k<<1|1].sum;
    else tree[k].sum=tree[k<<1].sum;
}
void change(int k,int p,int x){
    int l=tree[k].l,r=tree[k].r;
    if(l==r){
        tree[k].sum=x;
        return ;
    }
    int mid=(l+r)>>1;
    if(p<=mid)change(k<<1,p,x);
    else change(k<<1|1,p,x);
    pushup(k);
}
int query(int k,int tl,int tr){
    int l=tree[k].l,r=tree[k].r;
    if(tl<=l&&tr>=r){
        return tree[k].sum;
    }
    int mid=(l+r)>>1;
    int t1,t2;
    if(mid>=tl)t1=query(k<<1,tl,tr);
    if(mid<tr)t2=query(k<<1|1,tl,tr);
    if(t2&&mid<tr)return t2;
    else if(mid>=tl)return t1;
    else return 0;
}
int solvesum(int x){
    while(top[x]!=root){
        int ret=query(1,pos[top[x]],pos[x]);
        if(ret)return ret;
        x=f[top[x]];
    }
    return query(1,pos[top[x]],pos[x]);
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for(int i=1;i<=n-1;++i){
        int s,t;
        scanf("%d%d",&s,&t);
        add_edge(s,t);
    }
    dfs1(root);
    dfs2(root,root);
    change(1,1,1);
    for(int i=1;i<=m;++i){
        char opt[2];
        int t;
        scanf("%s%d",opt,&t);
        if(opt[0]=='C'){
            change(1,pos[t],t);
        }
        else{
            printf("%d\n",solvesum(t));
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Dream-Runner/p/9443482.html
今日推荐