【HIHOCODER 1576】 子树中的最小权值(线段树维护DFS序)

描述


给定一棵N个节点的树,编号1~N。其中1号节点是根,并且第i个节点的权值是Vi。
针对这棵树,小Hi会询问小Ho一系列问题。每次小Hi会指定一个节点x,询问小Ho以x为根的子树中,最小的权值是多少。为了增加难度,小Hi可能随时改变其中每个节点的权值。
你能帮助小Ho准确、快速的回答小Hi的问题吗?

输入


第一行一个正整数N。
第二行N个整数,V1, V2, ... VN。
第三行n-1个正整数,第i个数Pi表示第i+1号节点的父结点是第Pi号节点。注意1号节点是根。
第四行一个正整数Q,表示有Q个询问/修改权值。
接下来Q行,每行可能有如下两种输入格式:
1 x u
2 x
第一种表示将第x号节点的权值修改为u
第二种表示询问以第x号节点为根的子树中,最小的权值是多少。
对于30%的数据,1 ≤ N, Q ≤ 1000
对于100%的数据,1 ≤ N, Q ≤ 100000, -109 <= Vi, u <= 109

输出


对于每次询问,输出一个整数表示答案。

样例输入

12
3 5 -1 -2 9 6 2 8 -10 11 8 10
1 1 1 2 4 2 6 7 7 8 8
10
2 3
2 1
2 6
1 11 -5
1 5 -12
2 6
2 4
2 2
2 1
2 7

样例输出

-1
-10
6
-5
-5 
-12
-12
-10

题解


只需对这棵树求一个dfs序列,记录一个节点x前一次出现的位置和后一次出现的位置,那么在这个区间之内的节点都是它的子树节点,这样修改和查询都是区间维护,用线段树即可

#include <map>
#include <cmath>
#include <cstdio>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define inf 1000000000
#define PI acos(-1)
#define bug puts("here")
#define REP(i,x,n) for(int i=x;i<=n;i++)
#define DEP(i,n,x) for(int i=n;i>=x;i--)
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void Out(int a){
    if(a<0) putchar('-'),a=-a;
    if(a>=10) Out(a/10);
    putchar(a%10+'0');
}
const int N=1e5+5;
int n,q,x,y,tmp,cnt,tot;
int a[N],b[N],l[N],r[N],head[N];
struct Edge{
    int next,to;
}Path[N];
int C[N<<2];
void Addedge(int x,int y){
    Path[++cnt]=(Edge){head[x],y};
    head[x]=cnt;
}
void dfs(int x){
    b[++tot]=x;l[x]=tot;
    for(int i=head[x];i;i=Path[i].next){
        dfs(Path[i].to);
    }
    r[x]=tot;
}
void Pushup(int rt) {
     C[rt]=min(C[rt<<1],C[rt<<1|1]);
}
void Build(int rt,int l,int r){
    if (l==r){
        C[rt]=a[b[l]];
        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 pos,int x,int l,int r){
    if (l==r){
         C[rt]=x;
         return;
    }
    int mid=(l+r)>>1;
    if(pos<=mid) Update(rt<<1,pos,x,l,mid);
    if(pos>mid) Update(rt<<1|1,pos,x,mid+1,r);
    Pushup(rt);
}
int Query(int rt,int l,int r,int L,int R){
    if(L<=l&&r<=R) return C[rt];
    int mid=(l+r)>>1;
    int res=inf;
    if(L<=mid){res=min(res,Query(rt<<1,l,mid,L,R));}
    if(R>mid) {res=min(res,Query(rt<<1|1,mid+1,r,L,R));}
    return res;
}
int main(){
    n=read();
    REP(i,1,n) a[i]=read();
    REP(i,2,n){
        x=read();
        Addedge(x,i);
    }
    dfs(1);Build(1,1,n);
    q=read();
    while(q--){
        int op=read();
        if (op==1)
        {
            x=read();y=read();
            Update(1,l[x],y,1,n);
        }else{
            x=read();
            printf("%d
",Query(1,1,n,l[x],r[x]));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zsyacm666666/p/7553183.html