http://acm.hdu.edu.cn/showproblem.php?pid=5692
利用dfs序;
那么对于一个点的子区间就是时间撮上的一段;
这个直接线段树维护就好了;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define Ll long long
using namespace std;
const Ll N=1e5+5;
struct cs{Ll to,nxt;}a[N*2];
struct tree{Ll l,r,v,tag;}T[N*6];
Ll head[N],ll;
Ll d[N],v[N],l[N],r[N],f[N*3],t;
Ll n,m,x,y,z,tt;
void init(Ll x,Ll y){
a[++ll].to=y;
a[ll].nxt=head[x];
head[x]=ll;
}
void dfs(Ll x,Ll y){
d[x]+=d[y];
f[++t]=x;l[x]=t;
for(Ll k=head[x];k;k=a[k].nxt)
if(a[k].to!=y)dfs(a[k].to,x);
f[++t]=x;r[x]=t;
}
void up(Ll id){T[id].v=max(T[id*2].v,T[id*2+1].v);}
void make(Ll id,Ll l,Ll r){
T[id].l=l; T[id].r=r; T[id].tag=0;
if(l==r){
T[id].v=d[f[l]];
return;
}
Ll mid=l+r>>1;
make(id*2 ,l,mid );
make(id*2+1,mid+1,r);
up(id);
}
void push(Ll id){
if(!T[id].tag)return;
if(T[id].l!=T[id].r){
Ll x=id*2,y=x+1;
T[x].v+=T[id].tag;
T[y].v+=T[id].tag;
T[x].tag+=T[id].tag;
T[y].tag+=T[id].tag;
}
T[id].tag=0;
}
void change(Ll id,Ll x,Ll y,Ll z){
push(id);
if(x<=T[id].l&&T[id].r<=y){
T[id].v+=z;T[id].tag=z;
return;
}
if(T[id*2 ].r>=x)change(id*2 ,x,y,z);
if(T[id*2+1].l<=y)change(id*2+1,x,y,z);
up(id);
}
Ll out(Ll id,Ll x,Ll y){
push(id);
if(x<=T[id].l&&T[id].r<=y)return T[id].v;
Ll ans=-1e18;
if(T[id*2 ].r>=x)ans=max(ans,out(id*2 ,x,y));
if(T[id*2+1].l<=y)ans=max(ans,out(id*2+1,x,y));
return ans;
}
int main()
{
Ll num=0;
scanf("%lld",&tt);
while(tt--){
memset(head,0,sizeof head);ll=0;t=0;
printf("Case #%lld:\n",++num);
scanf("%lld%lld",&n,&m);
for(Ll i=1;i<n;i++){
scanf("%lld%lld",&x,&y);x++,y++;
init(x,y); init(y,x);
}
for(Ll i=1;i<=n;i++)scanf("%lld",&d[i]),v[i]=d[i];
dfs(1,0);
make(1,1,t);
while(m--){
scanf("%lld%lld",&z,&x);x++;
if(z==0){
scanf("%lld",&y);
change(1,l[x],r[x],y-v[x]);
v[x]=y;
}else printf("%lld\n",out(1,l[x],r[x]));
}
}
}
那么这道题很毒瘤的;
n=6,m=5;
如果我们一开始读入不是1~n-1而是1~m的话,样例稳过的;