好噁心的题啊。。。
each node except for node number 1 has the degree of at most 2 ... 真是好性质。..
一定要利用好这个的性质。。
然后。。
它只有根是有多个节点的。 也就是说除了根都是直链。。 每段直链开始用连续的序号标记, 成 2----K, 每段都这样处理
然后对这样产生的序号, build 出线段树, 更新某个点周围 d 距离, 就对应到每段直链的序号中进行update
update的时候。。如果发现d 到达了 根节点, 就在利用树状数组进行维护。 如果更新距离为d ,那么就是加在 deep - d + 1 的val上面。。
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstring>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int N = 211111;
#define LL long long
LL sum[N<<2|1];
LL cov[N<<2];
vector<int> vec[N];
int ra[N] , idx[N] , id_nn , top[N], fa[N] ,bottom[N];
int max_deep = 0;
int make_tree(int u,int Fa,int Top){
idx[u] = ++id_nn;
ra[id_nn] = u;
fa[u] = Fa;
top[u] = Top;
for(int i = 0;i < vec[u].size();i++){
int v = vec[u][i];
if(v!=Fa){
bottom[u] = make_tree(v,u,Top);
}
}
if(vec[u].size() <= 1){
return bottom[u]=u;
}
return bottom[u];
}
#define lowbit(x) ((x)&(-x))
LL dsum[N];
void qsum_update(int pos,LL val){
for( ; pos <= max_deep ; pos+=lowbit(pos)){
dsum[pos] += val;
}
}
LL getSum(int pos){
LL ret = 0;
//printf("sum pos=%d : ",pos);
for(; pos > 0 ; pos -= lowbit(pos))
ret += dsum[pos];
return ret;
}
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bass 1,id_nn,1
void push_down(int l,int r,int rt){
if(cov[rt]!=0){
sum[rt<<1] += (r-l+1 - (r-l+1)/2) * cov[rt];
sum[rt<<1|1] += (r-l+1)/2 * cov[rt];
cov[rt<<1] += cov[rt];
cov[rt<<1|1] += cov[rt];
cov[rt] = 0;
}
}
void push_up(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
int ql,qr,val;
void update(int l,int r,int rt){
if(ql<=l && r <= qr){
sum[rt] += (r-l+1) * val;
cov[rt] += val;
return;
}
push_down(l,r,rt);
int mid = (l+r)>>1;
if(ql <= mid)update(lson);
if(qr > mid)update(rson);
push_up(rt);
}
LL query(int l,int r,int rt){
push_down(l,r,rt);
if(l==r){
return sum[rt];
}
LL ans = 0;
int mid = (l+r)>>1;
if(ql <= mid) ans += query(lson);
if(qr > mid) ans += query(rson);
push_up(rt);
return ans;
}
void UPDATE_tree(int d){
ql=qr=1;
update(bass);
d--;
if(d==0)return;
//printf("zz d=%d val=%d\n",d,val);
d = min(d,max_deep);
d = max_deep - d + 1;
qsum_update(d,val);
}
void UPDATE(int v,int x,int d){
val = x;
if(v==1){
UPDATE_tree(d+1);
}else{
int idv = idx[v];
int idtopv = idx[top[v]];
int beggg,enddd;
if(idv - idtopv < d){
int dd = d - (idv-idtopv);
beggg = idtopv + dd - 1;
UPDATE_tree(dd);
}else{
beggg = idv - d;
}
enddd = min(idv + d , idx[bottom[v]]);
ql = beggg, qr = enddd;
if(ql<=qr)
update(bass);
}
}
LL QUERY(int u){
ql = qr = idx[u];
LL ans = query(bass);
if(u!=1){
int pos = idx[u] - idx[top[u]] + 1;
pos = max_deep - pos + 1;
ans += getSum(pos);
}
return ans;
}
int main(){
int n,m;
while(scanf("%d %d",&n,&m)!=EOF){
for(int i=1;i<=n;i++) vec[i].clear();
for(int i = 1,u,v;i < n;i++){
scanf("%d %d",&u,&v);
vec[u].push_back(v);
vec[v].push_back(u);
}
id_nn = 0;
ra[1]=idx[1]=++id_nn;
for(int i = 0;i < vec[1].size();i++){
make_tree(vec[1][i], 1, vec[1][i] );
max_deep = max(max_deep, idx[bottom[vec[1][i]]] - idx[vec[1][i]] +1 );
}
memset(dsum,0,sizeof(dsum));
memset(sum,0,sizeof(sum));
memset(cov,0,sizeof(cov));
for(int u,v,x,d; m--; ){
scanf("%d %d",&u,&v);
if(u==0){
scanf("%d %d",&x,&d);
UPDATE(v,x,d);
}else{
cout << QUERY(v) << endl;
}
}
}
return 0;
}