码迷,mamicode.com
首页 > 其他好文 > 详细

HDU5692 Snacks DFS+线段树

时间:2016-05-25 00:09:11      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:

分析:一棵以1为根的有根树,然后每个点维护从根到当前节点的路径和,当修改一个点时

只会影响的子树的和,最优值也是子树最大的值

技术分享
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=1e5+5;
const LL INF=1ll*1e11;
struct Edge{
  int v,next;
}edge[N<<1];
int head[N],tot;
void add(int u,int v){
  edge[tot].v=v;
  edge[tot].next=head[u];
  head[u]=tot++;
}
int s[N],t[N],clk,match[N],n,m,a[N];
LL sum[N],c[N<<2],lz[N<<2];
void dfs(int u,int f){
  s[u]=++clk;match[s[u]]=u;
  sum[u]+=sum[f];
  for(int i=head[u];~i;i=edge[i].next){
     int v=edge[i].v;
     if(v==f)continue;
     dfs(v,u);
  }
  t[u]=clk;
}
void up(int rt){
   c[rt]=max(c[rt<<1],c[rt<<1|1]);
}
void down(int rt){
   if(lz[rt]){
      c[rt<<1]+=lz[rt];
      c[rt<<1|1]+=lz[rt];
      lz[rt<<1]+=lz[rt];
      lz[rt<<1|1]+=lz[rt];
      lz[rt]=0;
   }
}
void build(int rt,int l,int r){
   lz[rt]=0;  
   if(l==r){c[rt]=sum[match[l]];return;}
   int m=(l+r)>>1;
   build(rt<<1,l,m);
   build(rt<<1|1,m+1,r);
   up(rt);
}
int tmp;
void modify(int rt,int l,int r,int x,int y){
  if(x<=l&&r<=y){
    lz[rt]+=1ll*tmp;
    c[rt]+=1ll*tmp;
    return;
  }
  int m=(l+r)>>1;
  down(rt);
  if(x<=m)modify(rt<<1,l,m,x,y);
  if(y>m)modify(rt<<1|1,m+1,r,x,y);
  up(rt);
}
LL ask(int rt,int l,int r,int x,int y){
  if(x<=l&&r<=y)return c[rt];
  LL ans=-INF;
  int m=(l+r)>>1;
  down(rt);
  if(x<=m)ans=max(ans,ask(rt<<1,l,m,x,y));
  if(y>m)ans=max(ans,ask(rt<<1|1,m+1,r,x,y));
  return ans;
}
int main()
{
    int T,cas=0;
    scanf("%d",&T);
    while(T--){
      printf("Case #%d:\n",++cas);
      scanf("%d%d",&n,&m);
      for(int i=1;i<=n;++i)head[i]=-1;
        clk=tot=0;
      for(int i=1;i<n;++i){
        int u,v;
        scanf("%d%d",&u,&v);
        ++u,++v;
        add(u,v),add(v,u);
      }
      for(int i=1;i<=n;++i)
        scanf("%I64d",&sum[i]),a[i]=(int)sum[i];
      dfs(1,0);
      build(1,1,n);
      for(int i=0;i<m;++i){
        int op,x,y;
        scanf("%d%d",&op,&x);
        ++x;
        if(!op){
          scanf("%d",&y);
          tmp=y-a[x];
          a[x]=y;
          if(tmp)modify(1,1,n,s[x],t[x]);
        }
        else{
          printf("%I64d\n",ask(1,1,n,s[x],t[x]));
        }
      }
    }
    return 0;
}
View Code

 

HDU5692 Snacks DFS+线段树

标签:

原文地址:http://www.cnblogs.com/shuguangzw/p/5525282.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!