5692 Snacks DFS序+線段樹
阿新 • • 發佈:2018-12-21
思路
求子樹x中到根節點的最大值。修改時需要將子樹x的所有點都修改。則本題變成一個區間更新,區間最值的題。dfs序處理後,套一個支援區間更新的線段樹即可。
每個葉子節點儲存的都是0到他所對應的標號(第幾臺零食機)的距離,每一次pushup時都會找出對應區間的最大值
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<algorithm> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int maxn=262144; ll sum[maxn],lazy[maxn],num[maxn/2],dis[maxn/2],val[maxn/2]; int in[maxn/2],out[maxn/2],head[maxn]; int time,cnt; struct node { int to , next; }e[maxn]; void add(int u , int v ) { e[cnt] = node{v,head[u]}; head[u] = cnt++ ; } void dfs( int x , int fa ) { in[x] = ++time; num[time] = dis[x]; for(int i = head[x] ; i != -1 ; i = e[i].next ) { int a = e[i].to; if( a == fa ) continue; dis[a] = dis[x] + val[a]; dfs( a , x ); } out[x] = time; } void pushup(int rt) { sum[rt] = max(sum[rt<<1],sum[rt<<1|1]); } void pushdown(int rt) { if( lazy[rt] ) { sum[rt<<1] += lazy[rt]; sum[rt<<1|1] += lazy[rt]; lazy[rt<<1] += lazy[rt]; lazy[rt<<1|1] += lazy[rt]; lazy[rt] = 0; } } void build(int l,int r,int rt) { lazy[rt]=0; if(l == r ) { sum[rt] = num[l]; return ; } int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); pushup(rt); } void update(int L,int R,ll c,int l,int r,int rt) { if(L<=l && R>=r) { sum[rt] += c; lazy[rt] += c; return ; } pushdown(rt); int m=(l+r)>>1; if(L <= m) update(L,R,c,l,m,rt<<1); if(R > m) update(L,R,c,m+1,r,rt<<1|1); pushup(rt); } ll query(int L,int R,int l,int r,int rt) { if( L<=l && R>=r ) return sum[rt]; pushdown(rt); int m = (l+r)>>1; ll ans=-1e18; //一開始開的不夠小 一直 wr if( L <= m ) ans=max(ans,query(L,R,l,m,rt<<1)); if( R > m ) ans=max(ans,query(L,R,m+1,r,rt<<1|1)); return ans; } int main() { int t,n,m; scanf("%d",&t); for(int k = 1 ; k <= t ; k++) { time=cnt=0; memset(head,-1,sizeof(head)); memset(dis,0,sizeof(dis)); int x,y,z; scanf("%d %d",&n,&m); for(int i=1 ; i<n ; i++ ) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } for(int i=0; i<n ; i++) scanf("%lld",&val[i]); dis[0]=val[0]; dfs(0,-1); build(1,n,1); printf("Case #%d:\n",k); for(int i=0 ; i<m ; i++) { ll v; scanf("%d",&z); if(z == 1) { scanf("%d",&x); printf("%lld\n",query(in[x],out[x],1,n,1)); } else { scanf("%d %lld",&x,&v); update(in[x],out[x],v-val[x],1,n,1); val[x]=v; } } } return 0; }