A little girl loves problems on trees very much. Here's one of them.
A tree is an undirected connected graph, not containing cycles. The degree of node x in the tree is the number of nodes y of the tree, such that each of them is connected with node x by some edge of the tree.
Let's consider a tree that consists of n nodes. We'll consider the tree's nodes indexed from 1 to n. The cosidered tree has the following property: each node except for node number 1 has the degree of at most 2.
Initially, each node of the tree contains number 0. Your task is to quickly process the requests of two types:
- Request of form: 0 v x d. In reply to the request you should add x to all numbers that are written in the nodes that are located at the distance of at most d from node v. The distance between two nodes is the number of edges on the shortest path between them.
- Request of form: 1 v. In reply to the request you should print the current number that is written in node v.
The first line contains integers n (2 ≤ n ≤ 105) and q (1 ≤ q ≤ 105) — the number of tree nodes and the number of requests, correspondingly.
Each of the next n - 1 lines contains two integers ui and vi (1 ≤ ui, vi ≤ n, ui ≠ vi), that show that there is an edge between nodes uiand vi. Each edge's description occurs in the input exactly once. It is guaranteed that the given graph is a tree that has the property that is described in the statement.
Next q lines describe the requests.
- The request to add has the following format: 0 v x d (1 ≤ v ≤ n, 1 ≤ x ≤ 104, 1 ≤ d < n).
- The request to print the node value has the following format: 1 v (1 ≤ v ≤ n).
The numbers in the lines are separated by single spaces.
For each request to print the node value print an integer — the reply to the request.
3 6
1 2
1 3
0 3 1 2
0 2 3 1
0 1 5 2
1 1
1 2
1 3
9
9
6
6 11
1 2
2 5
5 4
1 6
1 3
0 3 1 3
0 3 4 5
0 2 1 4
0 1 5 5
0 4 6 2
1 1
1 2
1 3
1 4
1 5
1 6
11
17
11
16
17
11
题意:给你一棵树,除了点1以为的点最多的度数为2,0表示以某个点v为半径d内的点权值+x
1表示查询v的权值大小;
思路:这题有一个关键点,就是除了1以为的度数最大为2,则表示如果以1为根的话,每条都是直链,没有开叉;
对于直链的话,可以进行dfs序标号,更新一条链的话就可以区间更新;
对于半径范围内的话,表示到根的距离减去d,以1为中心半径进行求解;
不能一条一条的去暴力链,开两个线段树,一个暴力一条链,一个存半径;
=_=,详见代码;
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cmath> #include<string> #include<queue> #include<algorithm> #include<stack> #include<cstring> #include<vector> #include<list> #include<set> #include<map> using namespace std; #define ll long long #define pi (4*atan(1.0)) #define eps 1e-14 #define bug(x) cout<<"bug"<<x<<endl; const int N=1e5+10,M=1e6+10,inf=2147483647; const ll INF=1e18+10,mod=2147493647; struct is { int v,next; } edge[N<<1]; int head[N],edg,dep[N]; int in[N],out[N],tot; void init() { memset(head,-1,sizeof(head)); edg=0; tot=0; } void add(int u,int v) { edg++; edge[edg].v=v; edge[edg].next=head[u]; head[u]=edg; } void dfs(int u,int fa,int deep) { dep[u]=deep; tot++; in[u]=tot; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(v==fa)continue; dfs(v,u,deep+1); } out[u]=tot; } struct linetree { int maxx[N<<2],lazy[N<<2]; void pushup(int pos) { maxx[pos]=max(maxx[pos<<1],maxx[pos<<1|1]); } void pushdown(int pos) { if(lazy[pos]) { int x=lazy[pos]; lazy[pos<<1]+=x; lazy[pos<<1|1]+=x; maxx[pos<<1|1]+=x; maxx[pos<<1]+=x; lazy[pos]=0; } } void build(int l,int r,int pos) { if(l==r) { maxx[pos]=0; lazy[pos]=0; return; } int mid=(l+r)>>1; build(l,mid,pos<<1); build(mid+1,r,pos<<1|1); pushup(pos); } void update(int L,int R,int c,int l,int r,int pos) { if(L<=l&&r<=R) { maxx[pos]+=c; lazy[pos]+=c; return; } pushdown(pos); int mid=(l+r)>>1; if(L<=mid) update(L,R,c,l,mid,pos<<1); if(R>mid) update(L,R,c,mid+1,r,pos<<1|1); pushup(pos); } int query(int p,int l,int r,int pos) { if(l==r)return maxx[pos]; pushdown(pos); int mid=(l+r)>>1; if(p<=mid) return query(p,l,mid,pos<<1); else return query(p,mid+1,r,pos<<1|1); } }; linetree tree,tree2; int main() { init(); int n,q; scanf("%d%d",&n,&q); for(int i=1; i<n; i++) { int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs(1,-1,0); tree.build(1,n,1); tree2.build(1,n,1); while(q--) { int flag; scanf("%d",&flag); if(flag) { int x; scanf("%d",&x); if(x!=1) printf("%d ",tree.query(in[x],1,n,1)+tree2.query(dep[x],1,n,1)); else printf("%d ",tree.query(in[1],1,n,1)); } else { int v,x,d; scanf("%d%d%d",&v,&x,&d); if(v==1) { tree.update(1,1,x,1,n,1); tree2.update(1,d,x,1,n,1); } else if(dep[v]<d) { int L=d-dep[v]; int l=in[v]-dep[v]+L+1; int r=min(in[v]+d,out[v]); tree2.update(1,L,x,1,n,1); tree.update(1,1,x,1,n,1); if(l<=r)tree.update(l,r,x,1,n,1); } else if(dep[v]==d) { int L=in[v]-d+1,R=min(out[v],in[v]+d); tree.update(L,R,x,1,n,1); tree.update(1,1,x,1,n,1); } else { int L=in[v]-d,R=min(out[v],in[v]+d); tree.update(L,R,x,1,n,1); } } } return 0; }