题目大意

给出一棵 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. [报错]java.lang.ClassCastException

    Caused by: java.lang.ClassCastException: org.apache.xml.dtm.ref.DTMManagerDefault cannot be cast to ...

  2. Mybatis-generator自动生成器

    目录 前言牢骚 Mybatis-generator是什么? Mybatis-generator怎么使用? 第一步,Maven文件引用 第二步,数据库建立 第三步,写mybatis-generator. ...

  3. 小程序图片转Base64

    在小程序中,有些业务要用到 图片的 base64 wx.chooseImage({ success: res => { wx.getFileSystemManager().readFile({ ...

  4. div宽高不确定,内容居中

    当div的宽高不确定时候,内容居中:// 加在父级div中 垂直居中:align-items:center; display: -webkit-flex;水平居中:justify-content:ce ...

  5. 【JS】长轮询

    循环请求服务器数据 function send () { xhr.open('GET', '/clock', true); xhr.onreadystatechange = function () { ...

  6. make: 警告:检测到时钟错误。您的创建可能是不完整的。

    问题: make: 警告:检测到时钟错误.您的创建可能是不完整的. 原因:1. 文件时间不一致.(或者修改了系统时间) 如何解决:你touch *一下,然后重新编译 touch * touch命令有两 ...

  7. tmux 后台训练

    参考链接:https://blog.csdn.net/u014381600/article/details/54588531

  8. c++ 智能指针用法详解

    本文介绍c++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c++11支持,并且第一个已经被c++11弃用. 为什么要使用智能 ...

  9. css的transform属性让子元素在父元素里面垂直水平居中

  10. pycharm导入自己写的模块时,模块下方出现红色波浪线的解决方案

    文章链接:https://blog.csdn.net/weixin_38383877/article/details/81121851 这种情况其实可以不用管,是可以正常运行的: 但是,如果看着不舒服 ...