【DFS序+线段树区间更新区间求最值】HDU 5692 Snacks
http://acm.hdu.edu.cn/showproblem.php?pid=5692
【思路】
- 每更新一个点,子树的所有结点都要更新,所以是区间更新
- 每查询一个点,子树的所有结点都要查询,所以是区间查询最值
- 线段树上结点的值是每个点到根这条链的权值和
【AC】
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<bits/stdc++.h> 3 #define lson l,mid,rt<<1 4 #define rson mid+1,r,rt<<1|1 5 using namespace std; 6 typedef long long ll; 7 int n,m; 8 const int maxn=1e5+2; 9 const int maxm=2*maxn; 10 const ll linf=1e18; 11 struct edge 12 { 13 int to; 14 int nxt; 15 }e[maxm]; 16 int head[maxn]; 17 int tot; 18 int cid; 19 int st[maxn],ed[maxn]; 20 ll tree[maxn]; 21 ll a[maxn]; 22 ll lazy[maxn*4]; 23 ll sum[maxn*4]; 24 int que[maxn]; 25 void init() 26 { 27 memset(head,-1,sizeof(head)); 28 tot=0; 29 cid=0; 30 memset(tree,0,sizeof(tree)); 31 memset(lazy,0,sizeof(lazy)); 32 } 33 void addedge(int u,int v) 34 { 35 e[tot].to=v; 36 e[tot].nxt=head[u]; 37 head[u]=tot++; 38 } 39 void dfs(int u,int pa) 40 { 41 st[u]=++cid; 42 que[cid]=u; 43 for(int i=head[u];i!=-1;i=e[i].nxt) 44 { 45 int v=e[i].to; 46 if(v==pa) continue; 47 tree[v]=tree[u]+a[v]; 48 dfs(v,u); 49 } 50 ed[u]=cid; 51 } 52 void pushup(int rt) 53 { 54 sum[rt]=max(sum[rt<<1],sum[rt<<1|1]); 55 return; 56 } 57 void pushdown(int rt) 58 { 59 if(lazy[rt]) 60 { 61 sum[rt<<1]+=lazy[rt]; 62 sum[rt<<1|1]+=lazy[rt]; 63 lazy[rt<<1]+=lazy[rt]; 64 lazy[rt<<1|1]+=lazy[rt]; 65 lazy[rt]=0; 66 } 67 } 68 void build(int l,int r,int rt) 69 { 70 lazy[rt]=0; 71 if(l==r) 72 { 73 sum[rt]=tree[que[l]]; 74 return; 75 } 76 int mid=(l+r)>>1; 77 build(lson); 78 build(rson); 79 pushup(rt); 80 } 81 82 void update(int L,int R,ll val,int l,int r,int rt) 83 { 84 if(L<=l && r<=R) 85 { 86 lazy[rt]+=val; 87 sum[rt]+=val; 88 return; 89 } 90 int mid=(l+r)>>1; 91 pushdown(rt); 92 if(L<=mid) 93 { 94 update(L,R,val,lson); 95 } 96 if(mid<R) 97 { 98 update(L,R,val,rson); 99 } 100 pushup(rt); 101 } 102 ll query(int L,int R,int l,int r,int rt) 103 { 104 if(L<=l && r<=R) 105 { 106 return sum[rt]; 107 } 108 pushdown(rt); 109 int mid=(l+r)>>1; 110 ll ans=-linf; 111 if(L<=mid) 112 { 113 ans=max(ans,query(L,R,lson)); 114 } 115 if(mid<R) 116 { 117 ans=max(ans,query(L,R,rson)); 118 } 119 return ans; 120 } 121 int main() 122 { 123 int T; 124 scanf("%d",&T); 125 int cas=0; 126 while(T--) 127 { 128 scanf("%d%d",&n,&m); 129 init(); 130 int u,v; 131 for(int i=1;i<=n-1;i++) 132 { 133 scanf("%d%d",&u,&v); 134 u++;v++; 135 addedge(u,v); 136 addedge(v,u); 137 } 138 for(int i=1;i<=n;i++) 139 { 140 scanf("%I64d",&a[i]); 141 } 142 tree[1]=a[1]; 143 dfs(1,-1); 144 build(1,cid,1); 145 printf("Case #%d:\n",++cas); 146 while(m--) 147 { 148 int tp; 149 scanf("%d",&tp); 150 if(tp==0) 151 { 152 int x;ll val; 153 scanf("%d%I64d",&x,&val); 154 x++; 155 update(st[x],ed[x],val-a[x],1,cid,1); 156 a[x]=val; 157 } 158 else 159 { 160 int x;scanf("%d",&x);x++; 161 ll ans=query(st[x],ed[x],1,cid,1); 162 printf("%I64d\n",ans); 163 } 164 } 165 } 166 return 0; 167 }
【注意】
线段树要开4倍空间,因为这个WA了好久