注意题目设定..除了根节点1外...其他的点至多两个度..而每个非点必须要有一个父亲..所以每个非根节点至多一个孩子..说明题目所给的树一定是这样的:
对于一个点的上下范围更新...有两种情况发生...一个是在所在的线段内更新...一个是上界超过了线段...更新到其他的线段上去...
对于N个线段..可以用N个线段树来维护其区间更新...但是对于跨过1点更新到其他线段的情况..若每次一条一条的更新..绝对超市..这是用一颗特殊的线段树来维护从1出发到多深..加了多少的值...
为了能方便的维护这颗特别的线段树...当其他的线段会更新到点1时...要做更新范围的调整..比如:
要在2号点更新距离为3的..那么更新范围是红色标出的部分...把这个部分分解为为黄色和红色的部分分别处理..红色就是在这个线段是做区间更新..黄色是在点1记录的距离上区间更新...
由于N+1颗线段树的长度是未知的..所以用vector来开...因为vector是动态申请空间的..并且可以通过下标直接访问元素...
Program:
#include<iostream> #include<stack> #include<queue> #include<stdio.h> #include<algorithm> #include<string.h> #include<cmath> #define ll long long #define oo 1000000007 #define MAXN 100004 using namespace std; struct node { int Tn,g; }P[MAXN]; vector<int> T[MAXN],col[MAXN],t0; int n,num,M[MAXN]; void dfs(int x,int m,int f,int t) { P[x].Tn=m,P[x].g=t; col[num].push_back(0); for (int i=0;i<T[x].size();i++) if (T[x][i]!=f) dfs(T[x][i],m,x,t+1); if (t>M[0]) M[0]=t; return; } void PushDown(int M,int len,int now) { if (!col[M][now]) return; col[M][now<<1]+=col[M][now]; col[M][(now<<1)|1]+=col[M][now]; col[M][now]=0; return; } void update(int M,int L,int R,int c,int l,int r,int now) // M用于确定是哪颗树 { if (L<=l && R>=r) { col[M][now]+=c; return; } PushDown(M,r-l+1,now); int mid=(l+r)>>1; if (L<=mid) update(M,L,R,c,l,mid,now<<1); if (R>mid) update(M,L,R,c,mid+1,r,(now<<1)|1); return; } int query(int M,int p,int l,int r,int now) { if (l==r) return col[M][now]; PushDown(M,r-l+1,now); int mid=(l+r)>>1; if (p<=mid) return query(M,p,l,mid,now<<1); if (p>mid) return query(M,p,mid+1,r,(now<<1)|1); } int main() { int i,q; scanf("%d%d",&n,&q); for (i=1;i<=n;i++) T[i].clear(); for (i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); T[x].push_back(y),T[y].push_back(x); } num=0,P[1].g=0,M[0]=0; for (i=0;i<T[1].size();i++) { col[++num].clear(),col[num].push_back(0); dfs(T[1][i],num,1,1); } col[0].clear(); i=M[0]<<2; while (i--) col[0].push_back(0); for (i=1;i<=num;i++) { int x=col[i].size(); M[i]=x-1,x<<=2; col[i].clear(); while (x--) col[i].push_back(0); } while (q--) { int tp,v,x,d; scanf("%d",&tp); if (!tp) { int l,r,p,t; scanf("%d%d%d",&v,&x,&d); if (P[v].g-d<=0) l=d-P[v].g+1,update(0,0,min(M[0],l-1),x,0,M[0],1); else l=P[v].g-d; if (v==1) continue; r=min(M[P[v].Tn],P[v].g+d); if (r<l) continue; update(P[v].Tn,l,r,x,1,M[P[v].Tn],1); }else { int ans=0; scanf("%d",&v); ans=query(0,P[v].g,0,M[0],1); if (v!=1) ans+=query(P[v].Tn,P[v].g,1,M[P[v].Tn],1); printf("%d\n",ans); } } return 0; }