【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 } 
View Code

 【注意】

线段树要开4倍空间,因为这个WA了好久

posted @ 2017-08-24 11:02  shulin15  阅读(176)  评论(0编辑  收藏  举报