题目
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lc o<<1
#define rc o<<1|1
typedef long long ll;
const int N=1e5+10;
int in[N<<1],out[N<<1],head[N],pre[N];
ll sum[N<<2],lazy[N<<2],val[N],a[N<<1],dis[N];
struct Edge{
int v,nx;
}edge[N<<1];
int t,m,n,tot,num;
inline void addedge(int u,int v)
{
edge[tot].v=v;
edge[tot].nx=head[u];
head[u]=tot++;
}
void dfs(int u,int fa)
{
in[u]=++num;
a[num]=dis[u];
for(int i=head[u];~i;i=edge[i].nx)
{
int v=edge[i].v;
if(v==fa)continue;
dis[v]=dis[u]+val[v];
dfs(v,u);
}
out[u]=num;
}
inline void push_up(int o){sum[o]=max(sum[lc],sum[rc]);}
void build(int o,int l,int r)
{
lazy[o]=0;
if(l==r){sum[o]=a[l];return;}
int mid=l+r>>1;
build(lc,l,mid);build(rc,mid+1,r);
push_up(o);
}
inline void push_down(int o,int l,int r)
{
if(!lazy[o])return;
sum[lc]+=lazy[o];
lazy[lc]+=lazy[o];
sum[rc]+=lazy[o];
lazy[rc]+=lazy[o];
lazy[o]=0;
}
ll query(int o,int l,int r,int nl,int nr)
{
if(nl<=l&&r<=nr)return sum[o];
push_down(o,l,r);
int mid=l+r>>1;
if(nr<=mid)return query(lc,l,mid,nl,nr);
else if(nl>mid)return query(rc,mid+1,r,nl,nr);
return max(query(lc,l,mid,nl,mid),query(rc,mid+1,r,mid+1,nr));
}
void update(int o,int l,int r,int nl,int nr,ll v)
{
if(nl<=l&&r<=nr)
{
sum[o]+=v;
lazy[o]+=v;
return;
}
push_down(o,l,r);
int mid=l+r>>1;
if(nr<=mid)update(lc,l,mid,nl,nr,v);
else if(nl>mid)update(rc,mid+1,r,nl,nr,v);
else update(lc,l,mid,nl,mid,v),update(rc,mid+1,r,mid+1,nr,v);
push_up(o);
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&t);
for(int ca=1;ca<=t;ca++)
{
memset(head,-1,sizeof(head));
num=0;
tot=0;
printf("Case #%d:\n",ca);
scanf("%d%d",&n,&m);
int u,v;
for(int i=1;i<n;i++)scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u);
for(int i=0;i<n;i++)scanf("%lld",&val[i]);
dis[0]=val[0];
dfs(0,0);
build(1,1,num);
int op,x;
ll y;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&op,&x);
if(op)printf("%lld\n",query(1,1,num,in[x],out[x]));
else scanf("%lld",&y),update(1,1,num,in[x],out[x],y-val[x]),val[x]=y;
}
}
return 0;
}
总结
dfs序是一段区间,可以用线段树的区间修改维护。
线段树用法挺灵活的,已经见过的用法有求区间和、区间最值、平方和、立方和、区间开根号、区间整除、区间取模、区间最大公约数、真子集、dfs序上的维护。