http://acm.hdu.edu.cn/showproblem.php?pid=5692

这道题真的是看了题解还搞了一天,把每条路径后序遍历按1-n重新标号,储存每个点在哪些路径中出现过(l和r数组),然后转化成线段树来更新和取最大值。

注意,如果使用递归建线段树,数组要开4n才能保证不超。

刚开始更新的函数每一遍更新了所有子树,然后超时了,后来在tree中加了个add,保存子树需要增加的量,如果用到这个子树,在把这个量加起来,简直巧妙。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define INF 0x3f3f3f3f
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; vector<int> line[];
int n,m,cnt,l[],r[];
long long w[],init[];
struct segtree
{
int left,right;
long long maxx,add;
}tree[]; void dfs(int now,int pre,long long sum)
{
sum += w[now];
int flag = ;
l[now] = INF;
for(int i = ;i < line[now].size();i++)
{
int next = line[now][i];
if(next == pre) continue;
flag = ;
dfs(next,now,sum);
l[now] = min(l[now],l[next]);
}
init[cnt] = sum;
r[now] = cnt++;
if(flag) l[now] = r[now];
} void build(int pos,int l,int r)
{
tree[pos].left = l;
tree[pos].right = r;
tree[pos].add = ;
if(l == r) tree[pos].maxx = init[l];
else
{
int mid = (l+r)/;
build(pos*,l,mid);
build(pos*+,mid+,r);
tree[pos].maxx = max(tree[pos*].maxx,tree[pos*+].maxx);
}
} void update(int pos,int l,int r,long long v)
{
if(tree[pos].add != )
{
if(tree[pos].left != tree[pos].right)
{
tree[pos*].maxx += tree[pos].add;
tree[pos*].add += tree[pos].add;
tree[pos*+].maxx += tree[pos].add;
tree[pos*+].add += tree[pos].add;
tree[pos].add = ;
}
}
if(tree[pos].left ==
l && r == tree[pos].right)
{
tree[pos].maxx += v;
tree[pos].add += v;
return;
}
int mid = (tree[pos].left+tree[pos].right)/;
if(r <= mid) update(pos*,l,r,v);
else if(l > mid) update(pos*+,l,r,v);
else
{
update(pos*,l,mid,v);
update(pos*+,mid+,r,v);
}
tree[pos].maxx = max(tree[pos*].maxx,tree[pos*+].maxx);
} long long getmax(int pos,int l,int r)
{
if(tree[pos].add != )
{
if(tree[pos].left != tree[pos].right)
{
tree[pos*].maxx += tree[pos].add;
tree[pos*].add += tree[pos].add;
tree[pos*+].maxx += tree[pos].add;
tree[pos*+].add += tree[pos].add;
tree[pos].add = ;
}
}
if(tree[pos].left == l && r == tree[pos].right) return tree[pos].maxx;
int mid = (tree[pos].left+tree[pos].right)/;
if(r <= mid) return getmax(pos*,l,r);
if(l > mid) return getmax(pos*+,l,r);
return max(getmax(pos*,l,mid),getmax(pos*+,mid+,r));
} int main()
{
int T;
scanf("%d",&T);
for(int z = ;z <= T;z++)
{
printf("Case #%d:\n",z);
scanf("%d%d",&n,&m);
for(int i = ;i < n;i++) line[i].clear();
for(int i = ;i < n-;i++)
{
int x,y;
scanf("%d%d",&x,&y);
line[x].push_back(y);
line[y].push_back(x);
}
for(int i = ;i < n;i++) scanf("%lld",&w[i]);
cnt = ;
dfs(,,);
build(,,n);
while(m--)
{
int op;
scanf("%d",&op);
if(op == )
{
int x,y;
scanf("%d%d",&x,&y);
long long temp = y-w[x];
w[x] = y;
update(,l[x],r[x],temp);
}
else
{
int x;
scanf("%d",&x);
printf("%lld\n",getmax(,l[x],r[x]));
}
}
}
return ;
}

最新文章

  1. Android必学——AsyncTask
  2. GroupJoin和Join的声明及调用
  3. 基于Token的身份验证——JWT
  4. PHP实现下载功能之流程分析
  5. centos6.5安装vsftp服务并配置虚拟账户ftp
  6. jQuery json数据处理
  7. sqoop:mysql和Hbase/Hive/Hdfs之间相互导入数据
  8. Codeforces 700E. Cool Slogans
  9. verilog中24LC04B iic(i2c)读写通信设计步骤,以及程序常见写法错误。
  10. PHP5.5.38版本Zend Guard loader for 5.5安装(详细)
  11. qsub
  12. ubuntu安装docker以及基本用法
  13. 前端 --- 2 css
  14. FreeSWITCH取消Digest校验流程
  15. PHP解决搜索时在URL地址栏输入中文字符搜索结果出现乱码
  16. linux内核设计与实现一书阅读整理 之第五章
  17. checkbox数据回显问题
  18. JSP的介绍及语法详解
  19. ssti记录
  20. poj 1067 取石子游戏 (威佐夫博弈)

热门文章

  1. Spring Cloud Stream消息驱动之RocketMQ入门(一)
  2. JavaScript中函数式编程中文翻译
  3. Win10系统下MySQL压缩版安装配置教程
  4. [转]C#中的abstract 类和方法
  5. SpringBoot入门(一)
  6. Scala实践12
  7. wireshark使用过程中,卡死未响应
  8. 自学 JAVA 的几点建议
  9. 引用dll出现的问题:发生一个或多个错误,引用无效或不支持该引用
  10. C#中的委托是什么