hiho1576 子樹中的最小權值【dfs序】
阿新 • • 發佈:2019-02-03
題意:求以x為根的子樹中的最小權值
思路:dfs序,把樹轉化成一個序列,類似LCA中的轉化,記錄1棵子樹進去的時間戳和出去的時間戳。線段樹求區間最小值
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<stdlib.h> #include<math.h> #include<vector> #include<list> #include<map> #include<set> #include<stack> #include<queue> #include<algorithm> #include<numeric> #include<functional> using namespace std; #define lson(x) 2*x #define rson(x) 2*x+1 typedef long long ll; typedef pair<int,int> pii; const int maxn = 100005; int in[maxn],out[maxn]; struct Edge { int to,next; }edge[maxn]; int head[maxn],tot,t; int a[maxn],num[maxn]; void init() { memset(head,-1,sizeof head); tot = 0; t = 0; } void add(int x,int y) { edge[tot].to = y; edge[tot].next = head[x]; head[x] = tot++; } void dfs(int x) { in[x] = ++t; num[t] = a[x]; for(int i = head[x]; i != -1; i = edge[i].next) { int y = edge[i].to; dfs(y); } out[x] = t; } struct data { int l,r,num,laz; }node[maxn*4]; void pushup(int cnt) { node[cnt].num = min(node[lson(cnt)].num,node[rson(cnt)].num); } void build(int x,int y, int cnt) { node[cnt].l = x; node[cnt].r = y; if(x == y) { node[cnt].num = num[x]; return; } int mid = (x+y) / 2; build(x,mid,lson(cnt)); build(mid+1,y,rson(cnt)); pushup(cnt); } void up(int x,int y,int cnt,int val) { if(x == node[cnt].l && y == node[cnt].r) { node[cnt].num = val; return; } int mid = (node[cnt].l + node[cnt].r) / 2; if(y <= mid) up(x,y,lson(cnt),val); else if(x >= mid+1) up(x,y,rson(cnt),val); else { up(x,mid,lson(cnt),val); up(mid+1,y,rson(cnt),val); } pushup(cnt); } int fid(int x,int y,int cnt) { if(x == node[cnt].l && y == node[cnt].r) { return node[cnt].num; } int mid = (node[cnt].l + node[cnt].r) / 2; if(y <= mid) return fid(x,y,lson(cnt)); else if(x >= mid+1) return fid(x,y,rson(cnt)); else return min( fid(x,mid,lson(cnt)) , fid(mid+1,y,rson(cnt))); } int main(void) { int n; while(scanf("%d",&n)!=EOF) { init(); for(int i = 1; i <= n; i++) scanf("%d",&a[i]); for(int i = 2; i <= n; i++) { int k; scanf("%d",&k); add(k,i); } dfs(1); build(1,n,1); int q; scanf("%d",&q); while(q--) { int op,x,u; scanf("%d",&op); if(op == 1) { scanf("%d%d",&x,&u); up(in[x],in[x],1,u); } else { scanf("%d",&x); printf("%d\n",fid(in[x],out[x],1)); } } } return 0; }