Reference: https://www.cnblogs.com/liyinggang/p/5965981.html
Question meaning: It is a data structure question, on the tree, in the order of dfs, it becomes linear;
Idea: For each node x, record its DFS sequence, including the sequence number of the first arrival, record it with in[x], and record the sequence number out[x] of leaving,
Open another array seg, in: (serial number -> the value of the node); out: (serial number -> the negative value of the node);
This will make
For trees: if the required interval completely contains an irrelevant subtree, this subtree does not affect the result;
For a linear-based segment tree, both in[x] and out[x] intervals are included, and the sum of the intervals is 0;
Use the line segment tree to build the array seg to get the sum of the intervals;
so,
1-->Update the corresponding values of in[x] and out[x] respectively;
2-->update in[x] to the value of out[x] interval;
3-->Return 1 (root) to in[x] interval;
#include <iostream> #include <cstdio> #include <vector> #define pb push_back using namespace std; typedef long long ll; const int maxn = 200050; ll sum[maxn*4]; ll seg[maxn],a[maxn],lazy[maxn*4],flag[maxn*4]; ll in[maxn],out[maxn]; ll io[maxn]; int cnt = 0; int n,m; vector <int> mp[maxn]; void dfs(int u,int fa) { cnt++; seg[cnt] = 1ll*a[u],in[u] = 1ll*cnt; for(int i=0; i< mp[u].size(); i++) { int tmp = mp[u][i]; if(tmp == fa)continue; dfs(tmp,u); } cnt++; seg[cnt] = -1ll*a[u],out[u] = 1ll*cnt; I [cnt] = - 1 ; } void pushup(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; flag[rt] = flag[rt<<1] + flag[rt<<1|1]; } void pushdown(int rt) { if(lazy[rt]) { lazy[rt<<1] += lazy[rt]; lazy[rt<<1|1]+= lazy[rt]; sum[rt<<1] += flag[rt<<1] * lazy[rt]; sum[rt<<1|1] += flag[rt<<1|1]*lazy[rt]; lazy[rt] = 0; } } void build(int rt,int l,int r) { if(l==r) { sum[rt] = seg[l]; if(io[l]==0)flag[rt] = 1; else flag[rt] = -1; return ; } int mid = (l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); pushup(rt); } void update_one( int pos, int d, int l, int r, int rt) // Single point update; { if (l == r) { if(flag[rt] ==1 ) sum[rt] += d; else sum[rt] -= d; return; } pushdown(rt); int mid = (l+r)>>1; if(pos<=mid) update_one(pos,d,l,mid,rt<<1); else update_one(pos,d,mid+1,r,rt<<1|1); pushup(rt); } void update_d(int L,int R,int d,int l,int r,int rt)//区间更新; { if(l >= L && R >= r) { sum[rt] += flag[rt]*d; lazy[rt] += d; return; } pushdown(rt); int mid = (l+r)>>1; if(L<=mid) update_d(L,R,d,l,mid,rt<<1); if(R>mid) update_d(L,R,d,mid+1,r,rt<<1|1); pushup(rt); } ll query(int L,int R,int l,int r,int rt)//区间查询 { if(l>=L&&r<=R) { return sum[rt]; } int mid = (l+r)>>1; ll res = 0; pushdown(rt); if(mid>=L)res += query(L,R,l,mid,rt<<1); if(mid<R)res +=query(L,R,mid+1,r,rt<<1|1); return res; } int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n;i++) { scanf("%lld" ,&a[i]); } for(int i=1; i<n;i++) { int u, v; scanf("%d%d",&u,&v); mp[v].pb(u); mp[u].pb(v); } dfs(1,0); build(1,1,2*n); for(int i=1 ;i <= m; i++) { int op, x, val; scanf("%d", &op); if(op==1) { scanf("%d%d",&x,&val); update_one(in[x],val,1,2*n,1); update_one(out[x],val,1,2*n,1); } else if (op == 2 ) { scanf("%d%d",&x,&val); update_d(in[x],out[x],val,1,2*n,1); } else if (op == 3 ) { scanf("%d",&x); printf("%lld\n",query(1,in[x],1,2*n,1)); } } return 0; }