题目大意

给出一棵 n 个点的无根树,待边权,要求维护一下操作:

  • 修改某条边的边权
  • 修改点 u 到点 v 路径上所有边的边权
  • 点 u 到点 v 路径上所有边的边权加上某个值
  • 查询点 u 到点 v 路径上所有边的边权最大值

Solution

边权下放后树链剖分 裸题,代码略长;

用线段树维护区间加、改、查操作,关于线段树多操作优先级的处理可以看这里

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std; const int maxn = 100007;
int n, a[maxn]; //edge-Table
int edgenum, head[maxn], nxt[maxn << 1], vet[maxn << 1], val[maxn << 1], id[maxn << 1], id_val[maxn];
inline void addedge(int u, int v, int cost, int ID){
++edgenum;
vet[edgenum] = v;
val[edgenum] = cost;
id[edgenum] = ID;
nxt[edgenum] = head[u];
head[u] = edgenum;
} //Segment Tree
int Max[maxn << 2], changetag[maxn << 2], addtag[maxn << 2];
inline void PushUp(int rt){
Max[rt] = max(Max[rt<<1], Max[rt<<1|1]);
} inline void PushDown(int rt, int ln, int rn){
if (changetag[rt] != -1){
Max[rt<<1] = changetag[rt]; Max[rt<<1|1] = changetag[rt];
changetag[rt << 1] = changetag[rt]; addtag[rt << 1] = 0;
changetag[rt << 1 | 1] = changetag[rt]; addtag[rt << 1 | 1] = 0;
changetag[rt] = -1;
}else if (addtag[rt]){
Max[rt<<1] += addtag[rt]; Max[rt<<1|1] += addtag[rt];
if (changetag[rt<<1] != -1) changetag[rt<<1] += addtag[rt];
else addtag[rt<<1] += addtag[rt];
if (changetag[rt<<1|1] != -1) changetag[rt<<1|1] += addtag[rt];
else addtag[rt<<1|1] += addtag[rt];
addtag[rt] = 0;
}
} void Change(int rt, int l, int r, int L, int R, int C){
if (L <= l && r <= R){
Max[rt] = C;
changetag[rt] = C;
addtag[rt] = 0;
return;
}
int m = (l + r) >> 1;
PushDown(rt, m - l + 1, r - m);
if (L <= m) Change(rt<<1, l, m, L, R, C);
if (R > m) Change(rt<<1|1, m+1, r, L, R, C);
PushUp(rt);
} void Add(int rt, int l, int r, int L, int R, int C){
if (L <= l && r <= R){
Max[rt] = Max[rt] + C;
if (changetag[rt] == -1) addtag[rt] += C;
else changetag[rt] += C;
return;
}
int m = (l + r) >> 1;
PushDown(rt, m - l + 1, r - m);
if (L <= m) Add(rt<<1, l, m, L, R, C);
if (R > m) Add(rt<<1|1, m+1, r, L, R, C);
PushUp(rt);
} int Query(int rt, int l, int r, int L, int R){
if (L <= l && r <= R) return Max[rt];
int m = (l + r) >> 1, res = -1;
PushDown(rt, m - l + 1, r - m);
if (L <= m) res = max(res, Query(rt<<1, l, m, L, R));
if (R > m) res = max(res, Query(rt<<1|1, m+1, r, L, R));
return res;
} //树剖
int size[maxn], tid[maxn], top[maxn], son[maxn], dep[maxn], stamp, dfspath[maxn], fa[maxn];
void dfs(int u, int D){
size[u] = 1; dep[u] = D; son[u] = 0;
for (int e = head[u]; e; e = nxt[e]){
int v = vet[e], cost = val[e], ID = id[e];
if (v == fa[u]) continue;
fa[v] = u; a[v] = cost; id_val[ID] = v;
dfs(v, D + 1);
size[u] += size[v];
if (size[v] > size[son[u]]) son[u] = v;
}
} void Dfs(int u, int ance){
top[u] = ance; tid[u] = ++stamp; dfspath[stamp] = u;
if (son[u])Dfs(son[u], ance);
for (int e = head[u]; e; e = nxt[e]){
int v = vet[e];
if (v != fa[u] && v != son[u]){
Dfs(v, v);
}
}
} int query(int u, int v){
int res = 0;
while (top[u] != top[v]){
if (dep[top[u]] < dep[top[v]]) swap(u, v);
res = max(res, Query(1, 1, n, tid[top[u]], tid[u]));
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap(u, v);
if (tid[u] < tid[v]) res = max(res, Query(1, 1, n, tid[u] + 1, tid[v]));
return res;
} void change(int u, int v, int val){
while (top[u] != top[v]){
if (dep[top[u]] < dep[top[v]]) swap(u, v);
Change(1, 1, n, tid[top[u]], tid[u], val);
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap(u, v);
if (tid[u] < tid[v]) Change(1, 1, n, tid[u] + 1, tid[v], val);
} void add(int u, int v, int val){
while (top[u] != top[v]){
if (dep[top[u]] < dep[top[v]]) swap(u, v);
Add(1, 1, n, tid[top[u]], tid[u], val);
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap(u, v);
if (tid[u] < tid[v]) Add(1, 1, n, tid[u] + 1, tid[v], val);
} inline int read(){
int f = 1, val = 0; char ch = getchar();
while ((ch < '0' || ch > '9') && (ch != '-')) ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') val = (val << 3) + (val << 1) + ch - '0', ch = getchar();
return val * f;
} void Build(int rt, int l, int r){
changetag[rt] = -1; addtag[rt] = 0;
if (l == r){
Max[rt] = a[dfspath[l]];
return;
}
int m = (l + r) >> 1;
Build(rt<<1, l, m);
Build(rt<<1|1, m+1, r);
PushUp(rt);
} int main(){
n = read();
for (int i = 1; i < n; ++i){
int u = read(), v = read(), cost = read();
addedge(u, v, cost, i);
addedge(v, u, cost, i);
}
dfs(1, 0);
Dfs(1, 1);
Build(1, 1, n);
char order[20];
scanf("%s", order);
while (order[0] != 'S'){
if (order[0] == 'M'){
int u = read(), v = read();
printf("%d\n", query(u, v));
}else if (order[0] == 'C' && order[1] == 'h'){
int k = read(), w = read();
Change(1, 1, n, tid[id_val[k]], tid[id_val[k]], w);
}else if (order[0] == 'C' && order[1] == 'o'){
int u = read(), v = read(), w = read();
change(u, v, w);
}else{
int u = read(), v = read(), w = read();
add(u, v, w);
}
scanf("%s", order);
}
return 0;
}

[BZOJ1984][Luogu4315]月下“毛景树”的更多相关文章

  1. 树剖+线段树||树链剖分||BZOJ1984||Luogu4315||月下“毛景树”

    题面:月下“毛景树” 题解:是道很裸的树剖,但处理的细节有点多(其实是自己线段树没学好).用一个Dfs把边权下移到点权,用E数组记录哪些边被用到了:前三个更新的操作都可以合并起来,可以发现a到b节点间 ...

  2. 【BZOJ1984】月下“毛景树” 树链剖分+线段树

    [BZOJ1984]月下"毛景树" Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校 ...

  3. [luogu4315]月下“毛景树”

    [luogu4315]月下"毛景树" luogu 联赛前复习一发树剖.不会告诉你WA了4发 #define ls x<<1,l,mid #define rs x< ...

  4. 【BZOJ-1984】月下“毛景树” 树链剖分

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1314  Solved: 416[Submit][Status][Discu ...

  5. BZOJ1984: 月下“毛景树”

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 713  Solved: 245[Submit][Status] Descri ...

  6. BZOJ 1984: 月下“毛景树” [树链剖分 边权]

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1728  Solved: 531[Submit][Status][Discu ...

  7. Bzoj 1984: 月下“毛景树” 树链剖分

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1282  Solved: 410[Submit][Status][Discu ...

  8. P4315 月下“毛景树”

    P4315 月下"毛景树" 题目描述 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里. 爬啊爬~爬啊爬 ...

  9. P4315 月下“毛景树”(树链剖分)

    P4315 月下"毛景树"(树链剖分) 题面 简述: 边权转点权(在dfs1处转换) 把一条边权赋值在深度更深的上 需要实现对单边权的染色 , 路径边权的染色 , 路径边权的增加 ...

随机推荐

  1. PHP之道 - php各方面的知识汇总

    看到一个PHP的知识各方面的汇总,写的很有借鉴意义,搬过来了 转自: https://laravel-china.github.io/php-the-right-way/ 欢迎阅读 其他语言版本 参与 ...

  2. 金融量化分析【day113】:布林带策略

    一.布林带策略简介 1.简介 2.计算公式 3.图形      二.布林带策略代码 import jqdata def initialize(context): set_benchmark('0000 ...

  3. 腾讯云服务器tomcat端口无法访问

    第一种情况: 如题:https://console.cloud.tencent.com/cvm/securitygroup 需要去这个地址设置安全组. 说实话,一句mmp不知当讲不当讲.使用说明这块太 ...

  4. HBase读写的几种方式(一)java篇

    1.HBase读写的方式概况 主要分为: 纯Java API读写HBase的方式: Spark读写HBase的方式: Flink读写HBase的方式: HBase通过Phoenix读写的方式: 第一种 ...

  5. 第六节:SignalR完结篇之依赖注入和分布式部署

    一. SignalR中DI思想的应用 DI,即依赖注入,它是一种不负责创建其自己的依赖项对象的一种模式,通常用来降低代码之间的耦合性,广泛应用于架构设计,是必不可少的一种思想. 下面结合一个需求来说一 ...

  6. Python系列之 - 异常处理

    python提供的异常处理 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行(通常是输入^C) Exception 常 ...

  7. SQL Server 数据库编程技巧

    Ø  简介 本文主要介绍 SQL Server 数据库在平常的开发中,可能会涉及到的编程技巧,主要包含以下内容: 1.   解决 SQL Server 不支持 127.0.0.1 登录 2.   查询 ...

  8. 【hdu 5632】Rikka with Array

    Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Ri ...

  9. 边框回归(bounding-Box regression)

    转自:https://blog.csdn.net/zijin0802034/article/details/77685438 为什么要边框回归? 什么是边框回归? 边框回归怎么做的? 边框回归为什么宽 ...

  10. java处理含有中文的字符串.

    1. 问题描述: 原始数据是以行为单位的, 每行固定长度931个字节, 汉字占2个字节, 按照字典描述,共有96个字典,只有第32个字典为中文地址, 所以需要单独处理. 由于项目设计保密,故删除敏感数 ...