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. 修改某一条边的权值为 ...
随机推荐
- Hadoop以及组件介绍
一.背景介绍 在接触过大数据相关项目的时候常常都会听到Hadoop这个东西,简单来说,他是一个用分布式计算来处理大数据的开源软件,下面包含了许多的组件和子项目,这篇文章将会介绍Hadoop的原理以及一 ...
- Java 发展简史:初生遇低谷,崛起于互联网
Java 起源与诞生 20世纪90年代,单片式计算机系统诞生,单片式计算机系统不仅廉价,而且功能强大,使用它可以大幅度提升消费性电子产品的智能化程度. SUN公司为了抢占市场先机,在1991年成立了一 ...
- netcore使用IOptions
{ "Logging": { "LogLevel": { "Default": "Information", " ...
- Prometheus+Alertmanager+Grafana监控组件容器部署
直接上部署配置文件 docker-compose.yml version: '3' networks: monitor: driver: bridge services: prometheus: im ...
- String中文字符转码
如何使用String构造方法和String.getBytes()做好中文字符转码 @Test public void test() { String testStr = "中"; ...
- Nmap使用教程(进阶篇)
什么是防火墙? 防火墙是用来控制网络访问的软件或硬件.分为以下两类:1.基于主机的防火墙:2.基于网络的防火墙. 基于主机的防火墙 这是在单台主机上运行的软件,用来控制入站流量(从网络向主机)和出站流 ...
- Python+Excel 操作对比
前言 从网页爬下来的大量数据需要excel清洗成堆的科学实验数据需要导入excel进行分析作为一名面向逼格的Python程序员该如何合理而又优雅的选择生产力工具呢? 得益于辛勤劳作的python大神们 ...
- .net core 不是开源的么 作为菜 不能贡献源码 只有 欣赏额
step one 去download一份 与前辈在一起
- Dynamics CRM 快速获取custom entity
我们可以使用Command来实现快速获取custom entity的值. 创建cmd 并且在nuget中引用 CRMSDK 复制下面的代码. userName 为登陆CRM的email passwo ...
- ThreeJS 物理材质shader源码分析(像素着色器)
再此之前推荐一款GLTF物理材质在线编辑器https://tinygltf.xyz/ 像素着色器(meshphysical_frag.glsl) #define PHYSICAL uniform ve ...