题意:给你一颗树,每次会修改一条边的边权,问修改之后的树的直径是多少?

思路:来源于:https://www.cnblogs.com/TinyWong/p/11260601.html

得到树的全序dfs序之后,我们考虑用线段树维护x - 2 * y + z。维护方法和2017, 2016那道题差不多,对于每个区间维护:x, -y, z, x - 2 * y, -2 * y + z, x - 2 * y + z6个部分的最大值,然后区间合并。

代码:

#include <bits/stdc++.h>
#define ls (o << 1)
#define rs (o << 1 | 1)
#define LL long long
#define INF 1e18
using namespace std;
const int maxn = 100010;
int lp[maxn], rp[maxn], mp[maxn * 2], tot;
vector<pair<int, long long> > G[maxn];
LL d[maxn];
void add(LL x, LL y, LL z) {
G[x].push_back(make_pair(y, z));
G[y].push_back(make_pair(x, z));
}
struct edge {
int u, v;
LL w;
};
edge a[maxn];
struct Seg {
LL v[6], lz;
//0: a
//1: b
//2: c
//3: a + 2 * b
//4: 2 * c + b
//5: a + b + 2 * c
};
Seg tr[maxn * 8];
void pushup(int o) {
//0:
tr[o].v[0] = max(tr[ls].v[0], tr[rs].v[0]);
//1:
tr[o].v[1] = max(tr[ls].v[1], tr[rs].v[1]);
//2:
tr[o].v[2] = max(tr[ls].v[2], tr[rs].v[2]);
//3:
tr[o].v[3] = max(tr[ls].v[3], tr[rs].v[3]);
tr[o].v[3] = max(tr[o].v[3], tr[ls].v[0] + 2ll * tr[rs].v[1]);
//4:
tr[o].v[4] = max(tr[ls].v[4], tr[rs].v[4]);
tr[o].v[4] = max(tr[o].v[4], 2ll * tr[ls].v[1] + tr[rs].v[2]);
//: 5
tr[o].v[5] = max(tr[ls].v[5], tr[rs].v[5]);
tr[o].v[5] = max(tr[o].v[5], tr[ls].v[3] + tr[rs].v[2]);
tr[o].v[5] = max(tr[o].v[5], tr[ls].v[0] + tr[rs].v[4]);
}
void maintain(int o, LL x) {
tr[o].lz += x;
tr[o].v[0] += x;
tr[o].v[1] -= x;
tr[o].v[2] += x;
tr[o].v[3] -= x;
tr[o].v[4] -= x;
}
void pushdown(int o) {
if(tr[o].lz) {
maintain(ls, tr[o].lz);
maintain(rs, tr[o].lz);
tr[o].lz = 0;
}
}
void build(int o, int l, int r) {
tr[o].lz = 0;
if(l == r) {
tr[o].v[0] = tr[o].v[2] = d[mp[l]];
tr[o].v[4] = tr[o].v[3] = tr[o].v[1] = -d[mp[l]];
tr[o].v[5] = 0;
return;
}
int mid = (l + r) >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
pushup(o);
}
void update(int o, int l, int r, int ql, int qr, LL val) {
if(l >= ql && r <= qr) {
maintain(o, val);
return;
}
int mid = (l + r) >> 1;
pushdown(o);
if(ql <= mid) update(ls, l, mid, ql, qr, val);
if(qr > mid) update(rs, mid + 1, r, ql, qr, val);
pushup(o);
}
void dfs(int x, int fa, LL dis) {
mp[++tot] = x;
lp[x] = tot;
rp[x] = tot;
d[x] = dis;
for (auto y : G[x]) {
if(y.first == fa) continue;
dfs(y.first, x, dis + y.second);
mp[++tot] = x;
rp[x] = tot;
}
}
int main() {
int n, m;
LL w, x, y, z;
scanf("%d%d%lld", &n, &m, &w);
for (int i = 1; i < n; i++) {
scanf("%lld%lld%lld", &x, &y, &z);
add(x, y, z);
a[i].u = x, a[i].v = y, a[i].w = z;
}
dfs(1, 0, 0);
build(1, 1, tot);
LL ans = 0;
while(m--) {
scanf("%lld%lld", &x, &y);
x = (x + ans) % (n - 1) + 1;
y = (y + ans) % w;
int p;
if(lp[a[x].u] < lp[a[x].v]) p = a[x].v;
else p = a[x].u;
update(1, 1, tot, lp[p], rp[p], y - a[x].w);
a[x].w = y;
ans = tr[1].v[5];
printf("%lld\n", ans);
}
}

  

Codeforces 1192B 全dfs序 + 线段树的更多相关文章

  1. Codeforces 916E(思维+dfs序+线段树+LCA)

    题面 传送门 题目大意:给定初始根节点为1的树,有3种操作 1.把根节点更换为r 2.将包含u,v的节点的最小子树(即lca(u,v)的子树)所有节点的值+x 3.查询v及其子树的值之和 分析 看到批 ...

  2. CodeForces 877E DFS序+线段树

    CodeForces 877E DFS序+线段树 题意 就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身 ...

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

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

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

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

  5. Codeforces Round #442 (Div. 2)A,B,C,D,E(STL,dp,贪心,bfs,dfs序+线段树)

    A. Alex and broken contest time limit per test 2 seconds memory limit per test 256 megabytes input s ...

  6. CodeForces 877E Danil and a Part-time Job(dfs序+线段树)

    Danil decided to earn some money, so he had found a part-time job. The interview have went well, so ...

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

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

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

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

  9. POJ 3321 DFS序+线段树

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

随机推荐

  1. Solr搜索引擎基础

    搜索引擎是指一个庞大的互联网资源数据库,如网页,新闻组,程序,图像等.它有助于在万维网上定位信息. 用户可以通过以关键字或短语的形式将查询传递到搜索引擎中来搜索信息. 搜索引擎然后搜索其数据库并向用户 ...

  2. Java数据结构之单链表

    这篇文章主要讲解了通过java实现单链表的操作,一般我们开始学习链表的时候,都是使用C语言,C语言中我们可以通过结构体来定义节点,但是在Java中,我们没有结构体,我们使用的是通过类来定义我们所需要的 ...

  3. 续上文,Unity3D面试ABC

    http://www.unitymanual.com/blog-3573-685.html 最先执行的方法是: 1.(激活时的初始化代码)Awake,2.Start.3.Update[FixUpdat ...

  4. 我用HTML写简历

    本文属于原创文章,转载请注明--来自桃源小盼的博客 起因 每次换工作写简历都是有点痛苦的事情,尤其是下载word模板,各种注册流程,有的还得买积分,冲会员,甚是不爽.就算下载好了,修改其中的一些细节也 ...

  5. GPG(pgp)加解密中文完整教程

    一.介绍 我们都知道,互联网是不安全的,但其上所使用的大部分应用,如Web.Email等一般都只提供明文传输方式(用https.smtps等例外).所以,当我们需要传输重要文件时,应该对当中的信息加密 ...

  6. 数据库为什么使用B+树而不是B树

    B树和B+树的区别主要有两点: 在B树中,你可以将键和值存放在内部节点和叶子节点,但在B+树中,内部节点都是键,没有值.叶子节点同时存放键和值 B+树的叶子节点有一条链相连,而B+树的叶子节点各自独立 ...

  7. 关于MonoBehaviour的单例通用规则

    长久以来,对于基于MonoBehaviour的单例总是心有梗结,总觉得用得很忐忑,今天,终于有时间思考和总结了下,理清了想通了.代码和注释如下: 其中GameLogic是我们自己的控制游戏生命周期的管 ...

  8. Java操作数据库之JDBC增删改查

    1.java连接MySql数据库 代码区域: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ...

  9. linux的find和grep区别?

    为什么会把 grep和find 这两个命令拿在一起来讨论? 是因为他们之间有一个容易混淆的地方, [在我的记忆中] : -name ? 它是find的选项! 不是grep的选项! 实际上, find基 ...

  10. fatal: repository 'xxxx' not found

    环境:centOS7  背景:公司代码仓库迁移,因而配置的jenkins自动打包git地址也要跟着变化. 问题描述:git clone http xxxx.git后报错: fatal: reposit ...