HDU_5692_dfs序+线段树
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 ;
}
HDU_5692_dfs序+线段树的更多相关文章
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
- Codeforces 343D Water Tree(DFS序 + 线段树)
题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...
- BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)
题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...
- POJ 3321 DFS序+线段树
单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4: 5: #include < ...
- 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树
题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...
- F - Change FZU - 2277 (DFS序+线段树)
题目链接: F - Change FZU - 2277 题目大意: 题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作 (1) 1 v k x : a[v] += x, a[v ' ...
- BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树
题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...
- BZOJ1103 [POI2007]大都市meg dfs序 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1103 题意概括 一棵树上,一开始所有的边权值为1,我们要支持两种操作: 1. 修改某一条边的权值为 ...
随机推荐
- 兄弟们,你们天天吊打面试官,面试官很难受啊。 metasploit免S客户端
metasploit生成的exe文件很小,但是免杀效果不行, 找了很多资料, 只有生成c语言shellcode,然后c#重新编译, 这种免杀效果,挺让人满意的 首先需要生成客户端,客户端使用了ngro ...
- 负载均衡之ribbon
一.什么是负载均衡? 做web开发都会接触到负载均衡,这里我们就不细说了. (摘自百度百科)负载均衡,英文名称为Load Balance,其含义就是指将负载(工作任务)进行平衡.分摊到多个操作单元上进 ...
- schedule of 2016-10-17~2016-10-23(Monday~Sunday)——1st semester of 2nd Grade
most important things to do 1.joint phd preparations 2.journal paper to write 3.solid fundamental kn ...
- Ubuntu18.04 一次性升级Python所有库
pip是什么 pip 是 Python 包管理工具,该工具提供了对Python 包的查找.下载.安装.卸载的功能. 升级pip版本 默认Ubuntu自带的pip (pip 9.0.1)是基于Pytho ...
- SpringBoot项目配置Date类型数据自动格式转换
application.yml加入配置 spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8
- 如何实施DevOps
对于长期在孤立的架构下工作的组织来说,转移到协作式DevOps系统似乎是难以成功的.为了进一步提高效率,必须改变观念,并进行团队文化改变.例如:许多人认为只有自动化工具才能解决DevOps,其实这是不 ...
- Docker学习(九)Volumn容器间共享数据
Docker学习(九)Volumn容器间共享数据 volume是什么 volume在英文中是容量的意思, 在docker中是数据卷的意思,是用来保存数据的容器 为什么要进行数据共享 在集群中有多台to ...
- vue需要知道哪些才能算作入门以及熟练
前两天接到一个面试官问我vue什么程度才算作可以用于开发,以前从没遇到过类似问题.只能大致说了一些,事后觉得也应该总结一下,前端vue这么火热那究竟什么才算做入门什么才算做熟练,只是我个人观点,不代表 ...
- Python入门小建议
"java从心"正式更名"KEN DO EVERTHING".Ken(Can) Do Everything,无所不能 Believe youseft then ...
- 深入理解大数据之——事务及其ACID特性
目录 事务简介 事物的定义 事务的目的 事务的状态 事务的ACID属性 ACID简介 原子性(Atomicity) 一致性(Consistency) 隔离性(Isolation) 持久性(Durabi ...