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

思路:来源于: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);
}
}

  

最新文章

  1. Asp.Net MVC&lt;五&gt;:过滤器
  2. Websocket通讯简析
  3. 21.2 Partitioning Types
  4. 在笔记本电脑开通无线WIFI
  5. CentOS 6.4 快速安装Nginx笔记
  6. CodeIgniter - 数据库的增删改查
  7. 关于Merge的整理--Merge的使用方法和注意事项的Demo
  8. 如何使用 yum 安装/更新/移除 软件
  9. CDockablepane风格设置
  10. Dagger2 入门解析
  11. webpack从0开始---(二)
  12. chrono--高精度计时
  13. 关于python深浅拷贝的个人浅见
  14. dos choice 命令
  15. [摘译] IK: 操纵关节式物体的反向动力学和几何约束
  16. java Base36 算法
  17. fastjson 返回json字符串,JSON.parse 报错
  18. Linux下跑程序,防止命令终端(断网,断电)
  19. Confluence 6 文档主题合并问答
  20. nginx启动重启与升级以及检测配置文件

热门文章

  1. 使用xshell远程连接Linux
  2. C++语法一二
  3. HDU 5172 GTY&#39;s gay friends (线段树)
  4. 高清摄像头MIPI接口与ARM连接【转】
  5. 【洛谷P2239 螺旋矩阵】
  6. 建立起BI的支撑团队
  7. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_08 Map集合_8_LinkedHashMap集合
  8. 如何减小VMware虚拟机硬盘空间
  9. Cassandra commands
  10. [10期]浅谈SSRF安全漏洞