题目大意

给出一棵 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. FreeNAS系统总结

    FreeNAS简介 FreeNAS是一套免费的NAS服务器,它能将一部普通PC变成网络存储服务器.该软件基于FreeBSD,Samba 及PHP,支持CIFS (samba), FTP, NFS pr ...

  2. SQL server 统计数据库表数量和列出所有表名称

    统计表数量 SELECT count(*) FROM sys.objects WHERE type='U' 列出表名称  SELECT NAME  FROM sys.objects WHERE typ ...

  3. Netty序章之BIO NIO AIO演变

    Netty序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用 ...

  4. Python生成器,迭代器,可迭代对象

    在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list,set,dict ...

  5. 第十二节: EF的三种模式(二) 之 ModelFirst模式(SQLServer为例)

    一. 简介  顾名思义,ModelFirst是模型优先,是DBFirst的逆向模式,先建立实体数据模型,然后根据实体数据模型来生成数据库,从而驱动整个开发流程.(生成一个空的edmx文件,手动在里面建 ...

  6. 还在用Json完成Ajax,改用Beetl吧

    原文链接:https://blog.csdn.net/xiandafu/article/details/44216905 作者:Beetl作者,闲大赋 浏览器通过AJAX,服务器返回json数据,无刷 ...

  7. Elasticsearch6.3.2启动过程源码阅读记录

    Elasticsearch6.3.2启动过程源码阅读记录 网上有很多关于es的源码分析,觉得自己技术深度还不够,所以这些文章只是看源码过程中的一个笔记,谈不上分析. 整个启动过程以类名.方法名,按顺序 ...

  8. Beamer中左边画图, 右边文字解释

    \begin{columns} \column{.4\textwidth} \begin{figure} \centering % Requires \usepackage{graphicx} \in ...

  9. C#中访问私有成员技巧

    源代码是别人的,你就不能修改源代码,只提供给你dll.或者你去维护别人的代码,源代码却有丢失.这样的情况如果你想知道私有成员的值,甚至去想直接调用类里面的私有方法.那怎么办呢?其实在.net中访问私有 ...

  10. luogu 3166 组合与gcd(数三角形)结论

    在n*m的点格图中选取三个点满足三角形的个数 结论:点(x1,y1)和(x2,y2) 中间有gcd(x2-x1,y2-y1)+1个和两点连成的线段直线共线 那么大力枚举 x2-x1和y2-y1,然后发 ...