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序+线段树的更多相关文章

  1. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  2. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  3. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  4. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

  5. POJ 3321 DFS序+线段树

    单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4:   5: #include < ...

  6. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

  7. F - Change FZU - 2277 (DFS序+线段树)

    题目链接: F - Change FZU - 2277 题目大意: 题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作 (1) 1 v k x : a[v] += x, a[v ' ...

  8. BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树

    题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...

  9. BZOJ1103 [POI2007]大都市meg dfs序 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1103 题意概括 一棵树上,一开始所有的边权值为1,我们要支持两种操作: 1. 修改某一条边的权值为 ...

随机推荐

  1. Hadoop以及组件介绍

    一.背景介绍 在接触过大数据相关项目的时候常常都会听到Hadoop这个东西,简单来说,他是一个用分布式计算来处理大数据的开源软件,下面包含了许多的组件和子项目,这篇文章将会介绍Hadoop的原理以及一 ...

  2. Java 发展简史:初生遇低谷,崛起于互联网

    Java 起源与诞生 20世纪90年代,单片式计算机系统诞生,单片式计算机系统不仅廉价,而且功能强大,使用它可以大幅度提升消费性电子产品的智能化程度. SUN公司为了抢占市场先机,在1991年成立了一 ...

  3. netcore使用IOptions

    { "Logging": { "LogLevel": { "Default": "Information", " ...

  4. Prometheus+Alertmanager+Grafana监控组件容器部署

    直接上部署配置文件 docker-compose.yml version: '3' networks: monitor: driver: bridge services: prometheus: im ...

  5. String中文字符转码

    如何使用String构造方法和String.getBytes()做好中文字符转码 @Test public void test() { String testStr = "中"; ...

  6. Nmap使用教程(进阶篇)

    什么是防火墙? 防火墙是用来控制网络访问的软件或硬件.分为以下两类:1.基于主机的防火墙:2.基于网络的防火墙. 基于主机的防火墙 这是在单台主机上运行的软件,用来控制入站流量(从网络向主机)和出站流 ...

  7. Python+Excel 操作对比

    前言 从网页爬下来的大量数据需要excel清洗成堆的科学实验数据需要导入excel进行分析作为一名面向逼格的Python程序员该如何合理而又优雅的选择生产力工具呢? 得益于辛勤劳作的python大神们 ...

  8. .net core 不是开源的么 作为菜 不能贡献源码 只有 欣赏额

    step one 去download一份 与前辈在一起

  9. Dynamics CRM 快速获取custom entity

    我们可以使用Command来实现快速获取custom entity的值. 创建cmd  并且在nuget中引用 CRMSDK 复制下面的代码. userName 为登陆CRM的email passwo ...

  10. ThreeJS 物理材质shader源码分析(像素着色器)

    再此之前推荐一款GLTF物理材质在线编辑器https://tinygltf.xyz/ 像素着色器(meshphysical_frag.glsl) #define PHYSICAL uniform ve ...