树链剖分专题

基础:DFS序+线段树

树链剖分

树链剖分学习:2018.9.7

HDU3966 Aragorn's Story

树上点到点最短路径区间点权修改,单点查询

#include<bits/stdc++.h>
using namespace std;
const int MAX=5e4+1;
struct P
{
    int to,nxt;
}e[MAX*2];
int head[MAX],top[MAX],fa[MAX],deep[MAX],num[MAX],p[MAX],fp[MAX],son[MAX],c[MAX],tot,pos;
int n,n_,m,a[MAX];
void init()
{
    tot=0;pos=1;
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
    memset(c,0,sizeof(c));
}
void adde(int u,int v)
{
    e[tot].to=v;e[tot].nxt=head[u];head[u]=tot++;
    e[tot].to=u;e[tot].nxt=head[v];head[v]=tot++;
}
void dfs(int u,int pre,int d)
{
    deep[u]=d;fa[u]=pre;num[u]=1;
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=pre)
        {
            dfs(v,u,d+1);
            num[u]+=num[v];
            if(son[u]==-1||num[v]>num[son[u]]) son[u]=v;
        }
    }
}
void getpos(int u,int sp)
{
    top[u]=sp;p[u]=pos++;fp[p[u]]=u;
    if(son[u]==-1) return ;
    getpos(son[u],sp);
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=son[u]&&v!=fa[u]) getpos(v,v);
    }
}
void add(int r, int v)
{
    while(r<=n) c[r]+=v,r+=r&(-r);
}
void add(int l,int r,int x)
{
    add(l,x),add(r+1,-x);
}
int get(int x)
{
    int sum=0;
    while(x) sum+=c[x],x-=x&(-x);
    return sum;
}
void update(int l,int r,int v)
{
    while(top[l]!=top[r])
    {
        if(deep[top[l]]<deep[top[r]]) swap(l,r);
        add(p[top[l]],p[l],v);
        l=fa[top[l]];
    }
    if(deep[l]>deep[r]) swap(l,r);
    add(p[l],p[r],v);
}
int main()
{
    int x,y,v;char c[5];
    while(~scanf("%d%d%d",&n,&n_,&m))
    {
        init();
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        for(int i=0;i<n_;++i) {scanf("%d%d",&x,&y);adde(x,y);}
        dfs(1,0,0);getpos(1,1);
        for(int i=1;i<=n;++i) add(p[i],p[i],a[i]);
        while(m--)
        {
            scanf("%s",c);
            if(c[0]=='D'||c[0]=='I') {scanf("%d%d%d",&x,&y,&v);update(x,y,c[0]=='I'?v:-v);}
            else {scanf("%d",&x);printf("%d\n",get(x));}
        }
    }
    return 0;
}

SPOJ QTREE

树上比权更新,点到点边权最大值区间查询:将边映射到深度更大的节点,排除LCA节点

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAX=1e5+5;
struct P
{
    int to,nxt;
}e[MAX*2];
int head[MAX],top[MAX],fa[MAX],deep[MAX],num[MAX],p[MAX],fp[MAX],son[MAX],tot,pos;
int t,n,m,a[MAX][3],b[MAX<<2];
void init()
{
    tot=0;pos=1;
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
    memset(b,0,sizeof(b));
}
void adde(int u,int v)
{
    e[tot].to=v;e[tot].nxt=head[u];head[u]=tot++;
    e[tot].to=u;e[tot].nxt=head[v];head[v]=tot++;
}
void dfs(int u,int pre,int d)
{
    deep[u]=d;fa[u]=pre;num[u]=1;
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=pre)
        {
            dfs(v,u,d+1);
            num[u]+=num[v];
            if(son[u]==-1||num[v]>num[son[u]]) son[u]=v;
        }
    }
}
void getpos(int u,int sp)
{
    top[u]=sp;p[u]=pos++;fp[p[u]]=u;
    if(son[u]==-1) return ;
    getpos(son[u],sp);
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=son[u]&&v!=fa[u]) getpos(v,v);
    }
}
void update(int rt,int l,int r,int pos,int val)
{
    if(l==r) {b[rt]=val;return ;}
    int mid=(l+r)>>1;
    if(pos<=mid) update(rt<<1,l,mid,pos,val);
    else update(rt<<1|1,mid+1,r,pos,val);
    b[rt]=max(b[rt<<1],b[rt<<1|1]);
}
int query(int rt,int l,int r,int L,int R)
{
    if(l>=L&&r<=R){return b[rt];}
    int mid=(l+r)>>1,ans=0;
    if(L<=mid) ans=max(ans,query(rt<<1,l,mid,L,R));
    if(R>mid) ans=max(ans,query(rt<<1|1,mid+1,r,L,R));
    return ans;
}
int query(int l,int r)
{
    int ans=0;
    while(top[l]!=top[r])
    {
        if(deep[top[l]]<deep[top[r]]) swap(l,r);
        ans=max(ans,query(1,1,pos-1,p[top[l]],p[l]));
        l=fa[top[l]];
    }
    if(l==r) return ans;
    if(deep[l]>deep[r]) swap(l,r);
    return ans=max(ans,query(1,1,pos-1,p[son[l]],p[r]));
}
int main()
{
    int x,y;char c[10];
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d",&n);
        for(int i=1;i<n;++i) {scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);adde(a[i][0],a[i][1]);}
        dfs(1,0,0);getpos(1,1);
        for(int i=1;i<n;++i)
        {
            if(deep[a[i][0]]<deep[a[i][1]]) swap(a[i][0],a[i][1]);
            update(1,1,pos-1,p[a[i][0]],a[i][2]);
        }
        while(~scanf("%s",c))
        {
            if(c[0]=='D') break;
            scanf("%d%d",&x,&y);
            if(c[0]=='C') update(1,1,pos-1,p[a[x][0]],y);
            else printf("%d\n",query(x,y));
        }
        printf("\n");
    }
    return 0;
}

POJ2763 Housewife Wind

树上边权更新,点到点边权和查询

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAX=1e5+5;
struct P
{
    int to,nxt;
}e[MAX*2];
int head[MAX],top[MAX],fa[MAX],deep[MAX],num[MAX],p[MAX],fp[MAX],son[MAX],eid[MAX],tot,pos;
int n,m,s,a[MAX][3],c[MAX];
void init()
{
    tot=0;pos=1;
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
    memset(c,0,sizeof(c));
}
void adde(int u,int v)
{
    e[tot].to=v;e[tot].nxt=head[u];head[u]=tot++;
    e[tot].to=u;e[tot].nxt=head[v];head[v]=tot++;
}
void dfs(int u,int pre,int d)
{
    deep[u]=d;fa[u]=pre;num[u]=1;
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=pre)
        {
            dfs(v,u,d+1);
            num[u]+=num[v];
            if(son[u]==-1||num[v]>num[son[u]]) son[u]=v;
        }
    }
}
void getpos(int u,int sp)
{
    top[u]=sp;p[u]=pos++;fp[p[u]]=u;
    if(son[u]==-1) return ;
    getpos(son[u],sp);
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=son[u]&&v!=fa[u]) getpos(v,v);
    }
}
void add(int x,int v)
{
    while(x<=pos-1) c[x]+=v,x+=x&(-x);
}
int get(int r)
{
    int sum=0;
    while(r) sum+=c[r],r-=r&(-r);
    return sum;
}
int get(int l, int r)
{
    return get(r)-get(l-1);
}
int query(int l,int r)
{
    int sum=0;
    while(top[l]!=top[r])
    {
        if(deep[top[l]]<deep[top[r]]) swap(l,r);
        sum+=get(p[top[l]],p[l]);
        l=fa[top[l]];
    }
    if(l==r) return sum;
    if(deep[l]>deep[r]) swap(l,r);
    return sum+get(p[son[l]],p[r]);
}
int main()
{
    int x,y,z;
    init();
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<n;++i) {scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);adde(a[i][0],a[i][1]);}
    dfs(1,0,0);getpos(1,1);
    for(int i=1;i<n;++i)
    {
        if(deep[a[i][0]]<deep[a[i][1]]) swap(a[i][0],a[i][1]);
        add(p[a[i][0]],a[i][2]);
    }
    while(m--)
    {
        scanf("%d",&z);
        if(z==1)
        {
            scanf("%d%d",&x,&y);
            add(p[a[x][0]],y-a[x][2]);
            a[x][2]=y;
        }
        else
        {
            scanf("%d",&x);
            printf("%d\n",query(s,x));
            s=x;
        }
    }
    return 0;
}

HYSBZ2243 染色

树上点到点区间更新,点到点区间查询相异连续段数(线段树区间合并)

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+5;
struct P
{
    int to,nxt;
}e[MAX<<1];
struct Px
{
    int l,r,v;
    Px(){l=r=-1;v=0;}
    void is(int a1,int a2,int a3){l=a1;r=a2;v=a3;}
}b[MAX<<2];
int head[MAX],top[MAX],fa[MAX],deep[MAX],num[MAX],p[MAX],fp[MAX],son[MAX],tot,pos;
int n,m,a[MAX],lz[MAX<<2];
void init()
{
    tot=0;pos=1;
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
    memset(lz,-1,sizeof(lz));
}
void adde(int u,int v)
{
    e[tot].to=v;e[tot].nxt=head[u];head[u]=tot++;
    e[tot].to=u;e[tot].nxt=head[v];head[v]=tot++;
}
void dfs(int u,int pre,int d)
{
    deep[u]=d;fa[u]=pre;num[u]=1;
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=pre)
        {
            dfs(v,u,d+1);
            num[u]+=num[v];
            if(son[u]==-1||num[v]>num[son[u]]) son[u]=v;
        }
    }
}
void getpos(int u,int sp)
{
    top[u]=sp;p[u]=pos++;fp[p[u]]=u;
    if(son[u]==-1) return ;
    getpos(son[u],sp);
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=son[u]&&v!=fa[u]) getpos(v,v);
    }
}
inline Px merge_(const Px &x,const Px &y)
{
    if(x.v==0) return y;
    if(y.v==0) return x;
    Px t;
    t.is(x.l,y.r,x.v+y.v);
    if(x.r==y.l) --t.v;
    return t;
}
inline void pushup(int rt)
{
    b[rt].is(b[rt<<1].l,b[rt<<1|1].r,b[rt<<1].v+b[rt<<1|1].v);
    if(b[rt<<1].r==b[rt<<1|1].l) --b[rt].v;
}
inline void pushdown(int rt)
{
    b[rt<<1].is(lz[rt],lz[rt],1);
    b[rt<<1|1].is(lz[rt],lz[rt],1);
    lz[rt<<1]=lz[rt<<1|1]=lz[rt];
    lz[rt]=-1;
}
void build(int rt,int l,int r)
{
    if(l==r) {b[rt].is(a[fp[r]],a[fp[r]],1);return ;}
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}
void update(int rt,int l,int r,int L,int R,int v)
{
    if(L<=l&&R>=r) {b[rt].is(v,v,1);lz[rt]=v;return ;}
    if(lz[rt]!=-1) pushdown(rt);
    int mid=(l+r)>>1;
    if(L<=mid) update(rt<<1,l,mid,L,R,v);
    if(R>mid) update(rt<<1|1,mid+1,r,L,R,v);
    pushup(rt);
}
Px query(int rt,int l,int r,int L,int R)
{
    if(L<=l&&R>=r) return b[rt];
    if(lz[rt]!=-1) pushdown(rt);
    int mid=(l+r)>>1;Px t;
    if(L<=mid) t=query(rt<<1,l,mid,L,R);
    if(R>mid) t=merge_(t,query(rt<<1|1,mid+1,r,L,R));
    return t;
}
void update(int l,int r,int v)
{
    while(top[l]!=top[r])
    {
        if(deep[top[l]]<deep[top[r]]) swap(l,r);
        update(1,1,n,p[top[l]],p[l],v);
        l=fa[top[l]];
    }
    if(deep[l]>deep[r]) swap(l,r);
    update(1,1,n,p[l],p[r],v);
}
int query(int l,int r)
{
    Px L,R;
    while(top[l]!=top[r])
    {
        if(deep[top[l]]<deep[top[r]]) {swap(l,r);swap(L,R);}
        L=merge_(query(1,1,n,p[top[l]],p[l]),L);
        l=fa[top[l]];
    }
    if(deep[l]>deep[r]) {swap(l,r);swap(L,R);}
    R=merge_(query(1,1,n,p[l],p[r]),R);
    return L.v+R.v-(L.l==R.l?1:0);
}
int main()
{
    int x,y,z;char c[10];
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        for(int i=1;i<n;++i) {scanf("%d%d",&x,&y);adde(x,y);}
        dfs(1,0,0);getpos(1,1);
        build(1,1,n);
        while(m--)
        {
            scanf("%s",c);
            if(c[0]=='C')
            {
                scanf("%d%d%d",&x,&y,&z);
                update(x,y,z);
            }
            else
            {
                scanf("%d%d",&x,&y);
                printf("%d\n",query(x,y));
            }
        }
    }
    return 0;
}

HDU5052 Yaoge’s maximum profit

树上点到点区间更新,树上点到点区间查询正向最大差值(线段树区间合并维护左右区间最值、正向逆向最大差值:题目要求有方向)

#include<bits/stdc++.h>
using namespace std;
const int MAX=5e4+5;
struct P
{
    int to,nxt;
}e[MAX<<1];
struct Px
{
    long long in,ax,nx,xn;
    Px(){in=ax=nx=xn=-1;}
    void is(long long a1,long long a2,long long a3,long long a4){in=a1;ax=a2;nx=a3;xn=a4;}
    void add(long long c){in+=c;ax+=c;}
}b[MAX<<2];
int head[MAX],top[MAX],fa[MAX],deep[MAX],num[MAX],p[MAX],fp[MAX],son[MAX],tot,pos;
int t,n,m,a[MAX];
long long lz[MAX<<2];
void init()
{
    tot=0;pos=1;
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
    memset(lz,0,sizeof(lz));
}
void adde(int u,int v)
{
    e[tot].to=v;e[tot].nxt=head[u];head[u]=tot++;
    e[tot].to=u;e[tot].nxt=head[v];head[v]=tot++;
}
void dfs(int u,int pre,int d)
{
    deep[u]=d;fa[u]=pre;num[u]=1;
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=pre)
        {
            dfs(v,u,d+1);
            num[u]+=num[v];
            if(son[u]==-1||num[v]>num[son[u]]) son[u]=v;
        }
    }
}
void getpos(int u,int sp)
{
    top[u]=sp;p[u]=pos++;fp[p[u]]=u;
    if(son[u]==-1) return ;
    getpos(son[u],sp);
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=son[u]&&v!=fa[u]) getpos(v,v);
    }
}
inline Px merge_(const Px &x,const Px &y)
{
    if(x.in==-1) return y;
    if(y.in==-1) return x;
    Px t;
    t.is(min(x.in,y.in),
         max(x.ax,y.ax),
         max(y.ax-x.in,max(x.nx,y.nx)),
         max(x.ax-y.in,max(x.xn,y.xn)));
    return t;
}
inline void pushup(int rt)
{
    b[rt].is(min(b[rt<<1].in,b[rt<<1|1].in),
             max(b[rt<<1].ax,b[rt<<1|1].ax),
             max(b[rt<<1|1].ax-b[rt<<1].in,max(b[rt<<1].nx,b[rt<<1|1].nx)),
             max(b[rt<<1].ax-b[rt<<1|1].in,max(b[rt<<1].xn,b[rt<<1|1].xn)));
}
inline void pushdown(int rt)
{
    b[rt<<1].add(lz[rt]);
    b[rt<<1|1].add(lz[rt]);
    lz[rt<<1]+=lz[rt];
    lz[rt<<1|1]+=lz[rt];
    lz[rt]=0;
}
void build(int rt,int l,int r)
{
    if(l==r) {b[rt].is(a[fp[r]],a[fp[r]],0,0);return ;}
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}
void update(int rt,int l,int r,int L,int R,long long c)
{
    if(L<=l&&R>=r) {b[rt].add(c);lz[rt]+=c;return ;}
    if(lz[rt]>0) pushdown(rt);
    int mid=(l+r)>>1;
    if(L<=mid) update(rt<<1,l,mid,L,R,c);
    if(R>mid) update(rt<<1|1,mid+1,r,L,R,c);
    pushup(rt);
}
Px query(int rt,int l,int r,int L,int R)
{
    if(L<=l&&R>=r) return b[rt];
    if(lz[rt]>0) pushdown(rt);
    int mid=(l+r)>>1;Px t;
    if(L<=mid) t=query(rt<<1,l,mid,L,R);
    if(R>mid) t=merge_(t,query(rt<<1|1,mid+1,r,L,R));
    return t;
}
void update(int l,int r,long long c)
{
    while(top[l]!=top[r])
    {
        if(deep[top[l]]<deep[top[r]]) swap(l,r);
        update(1,1,n,p[top[l]],p[l],c);
        l=fa[top[l]];
    }
    if(deep[l]>deep[r]) swap(l,r);
    update(1,1,n,p[l],p[r],c);
}
long long query(int l,int r)
{
    Px L,R;
    while(top[l]!=top[r])
    {
        if(deep[top[l]]<deep[top[r]])
        {
            R=merge_(query(1,1,n,p[top[r]],p[r]),R);
            r=fa[top[r]];
        }
        else
        {
            L=merge_(query(1,1,n,p[top[l]],p[l]),L);
            l=fa[top[l]];
        }
    }
    if(deep[l]>deep[r]) L=merge_(query(1,1,n,p[r],p[l]),L);
    else R=merge_(query(1,1,n,p[l],p[r]),R);
    long long ans;
    if(L.in==-1) ans=R.nx;
    else if(R.in==-1) ans=L.xn;
    else ans=max(R.ax-L.in,max(L.xn,R.nx));
    return ans<0?0:ans;
}
int main()
{
    int x,y;long long z;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        for(int i=1;i<n;++i) {scanf("%d%d",&x,&y);adde(x,y);}
        dfs(1,0,0);getpos(1,1);
        build(1,1,n);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d%I64d",&x,&y,&z);
            printf("%I64d\n",query(x,y));
            update(x,y,z);
        }
    }
    return 0;
}

HYSBZ-4043 树上操作

树上单点、子树区间更新,树上点到根节点区间求和(DFS序+树链剖分)

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+5;
struct P
{
    int to,nxt;
}e[MAX<<1];
int head[MAX],top[MAX],fa[MAX],deep[MAX],num[MAX],p[MAX],fp[MAX],son[MAX],tot,pos;
int n,m,a[MAX],out[MAX];
long long b[MAX<<2],lz[MAX<<2];
void init()
{
    tot=0;pos=1;
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
    memset(lz,0,sizeof(lz));
}
void adde(int u,int v)
{
    e[tot].to=v;e[tot].nxt=head[u];head[u]=tot++;
    e[tot].to=u;e[tot].nxt=head[v];head[v]=tot++;
}
void dfs(int u,int pre,int d)
{
    deep[u]=d;fa[u]=pre;num[u]=1;
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=pre)
        {
            dfs(v,u,d+1);
            num[u]+=num[v];
            if(son[u]==-1||num[v]>num[son[u]]) son[u]=v;
        }
    }
}
void getpos(int u,int sp)
{
    top[u]=sp;p[u]=pos++;fp[p[u]]=u;
    if(son[u]==-1) {out[u]=pos-1;return ;}
    getpos(son[u],sp);
    for(int i=head[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].to;
        if(v!=son[u]&&v!=fa[u]) getpos(v,v);
    }
    out[u]=pos-1;
}
inline void pushup(int rt)
{
    b[rt]=b[rt<<1]+b[rt<<1|1];
}
inline void pushdown(int rt,int l,int r,int mid)
{
    b[rt<<1]+=lz[rt]*(mid-l+1);
    b[rt<<1|1]+=lz[rt]*(r-mid);
    lz[rt<<1]+=lz[rt];
    lz[rt<<1|1]+=lz[rt];
    lz[rt]=0;
}
void build(int rt,int l,int r)
{
    if(l==r) {b[rt]=a[fp[r]];return ;}
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}
void update(int rt,int l,int r,int x,long long c)
{
    if(l==r) {b[rt]+=c;return ;}
    int mid=(l+r)>>1;
    if(lz[rt]) pushdown(rt,l,r,mid);
    if(x<=mid) update(rt<<1,l,mid,x,c);
    else update(rt<<1|1,mid+1,r,x,c);
    pushup(rt);
}
void update(int rt,int l,int r,int L,int R,long long c)
{
    if(L<=l&&R>=r) {b[rt]+=c*(r-l+1);lz[rt]+=c;return ;}
    int mid=(l+r)>>1;
    if(lz[rt]) pushdown(rt,l,r,mid);
    if(L<=mid) update(rt<<1,l,mid,L,R,c);
    if(R>mid) update(rt<<1|1,mid+1,r,L,R,c);
    pushup(rt);
}
long long query(int rt,int l,int r,int L,int R)
{
    if(L<=l&&R>=r) return b[rt];
    int mid=(l+r)>>1;long long sum=0;
    if(lz[rt]) pushdown(rt,l,r,mid);
    if(L<=mid) sum=query(rt<<1,l,mid,L,R);
    if(R>mid) sum+=query(rt<<1|1,mid+1,r,L,R);
    return sum;
}
long long query(int x)
{
    long long ans=0;
    while(top[x]!=1)
    {
        ans+=query(1,1,n,p[top[x]],p[x]);
        x=fa[top[x]];
    }
    ans+=query(1,1,n,p[top[x]],p[x]);
    return ans;
}
int main()
{
    int x,y,z;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        for(int i=1;i<n;++i) {scanf("%d%d",&x,&y);adde(x,y);}
        dfs(1,0,0);getpos(1,1);
        build(1,1,n);
        while(m--)
        {
            scanf("%d",&z);
            if(z==1)
            {
                scanf("%d%d",&x,&y);
                update(1,1,n,p[x],y);
            }
            else if(z==2)
            {
                scanf("%d%d",&x,&y);
                update(1,1,n,p[x],out[x],y);
            }
            else
            {
                scanf("%d",&x);
                printf("%lld\n",query(x));
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Nrtostp/article/details/82353911