题意:
中文题
思路:
维护DFS序,得到点i的时间戳le[i],跟子树最大时间戳re[i],由于DFS序le[i]跟re[i]必定连续
线段树维护每个点到根节点的路径最大值,叶子节点代表路径的值
修改就是修改le[i]~re[i]的值,查询就是查询最大值
WA点:long long, 线段树更新了,但是点值忘记更新了,线段树数组开小,inf开太小
2286ms#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #define ll long long #define lc o<<1 #define rc o<<1|1 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int maxn=1e5+5; const ll inf=2000000000000000000; int head[maxn];int nxt[2*maxn];int to[2*maxn]; int le[maxn];int re[maxn]; int rnk[maxn];ll path[maxn]; ll lazy[maxn*4];ll val[maxn*4];ll a[maxn]; int cnt=0,idx=0; void add(int u,int v){cnt++;nxt[cnt]=head[u];head[u]=cnt;to[cnt]=v;} void init(){cnt=idx=0;memset(head,-1,sizeof(head));memset(path,0,sizeof(path));} void dfs(int u,int p) { le[u]=re[u]=++idx;rnk[idx]=u; path[u]=path[p]+1ll*a[u]; for(int i=head[u];i!=-1;i=nxt[i]) { int v=to[i]; if(v==p)continue; dfs(v,u); re[u]=max(re[u],re[v]); } } void pushup(int o){ val[o]=max(val[lc],val[rc]);} void pushdown(int o) { if(lazy[o]!=0) { val[lc]+=1ll*lazy[o]; val[rc]+=1ll*lazy[o]; lazy[lc]+=lazy[o]; lazy[rc]+=lazy[o]; lazy[o]=0; } } void build(int o,int L,int R) { if(L==R) { val[o]=path[rnk[L]]; return ; } val[o]=-inf; lazy[o]=0; int m=(L+R)>>1; build(lc,L,m);build(rc,m+1,R); pushup(o); } void update(int o,int L,int R,int ql,int qr,int addval) { if(ql<=L&&qr>=R) { val[o]+=1ll*addval; lazy[o]+=addval; return ; } int m=(L+R)>>1; pushdown(o); if(ql<=m)update(lc,L,m,ql,qr,addval); if(qr>m) update(rc,m+1,R,ql,qr,addval); pushup(o); } ll query(int o,int L,int R,int ql,int qr) { if(ql<=L&&qr>=R) return val[o]; int m=(L+R)>>1; pushdown(o); ll ans=-inf; if(ql<=m)ans=max(ans,query(lc,L,m,ql,qr)); if(qr>m) ans=max(ans,query(rc,m+1,R,ql,qr)); return ans; } int main() { int T;int kase=0; scanf("%d",&T); while(T--) { int n,q;int u,v; scanf("%d %d",&n,&q);init(); for(int i=1;i<n;i++) { scanf("%d %d",&u,&v);u++,v++; add(u,v);add(v,u); } for(int i=1;i<=n;i++)scanf("%I64d",&a[i]); dfs(1,0);build(1,1,n); //for(int i=1;i<=n;i++) printf("i=%d le=%d re=%d path=%d\n ",i,le[i],re[i],path[i]); int type=0;ll x,y; printf("Case #%d:\n",++kase); for(int i=1;i<=q;i++) { scanf("%d",&type); if(type==0) { scanf("%I64d %I64d",&x,&y); x++; update(1,1,n,le[x],re[x],y-a[x]); a[x]=y; } if(type==1) { scanf("%I64d",&x);x++; printf("%I64d\n",query(1,1,n,le[x],re[x])); } } } }