题目大意

给出一棵 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. 分布式监控系统开发【day38】:监控数据如何画图(九)

    一.画图代码 1.收集处理数据 class GraphGenerator(object): ''' generate graphs ''' def __init__(self,request,redi ...

  2. 金融量化分析【day112】:初识量化交易

    一.摘要 为什么需要量化交易? 量化交易是做什么? 量化交易的价值何在? 做量化交易需要什么? 聚宽是什么? 零基础如何快速入门量化交易? 自测与自学 二.量化交易比传统交易强多少? 它能让你的交易效 ...

  3. Shell脚本之grep

    1. 过滤空行   grep -v ^$

  4. win7 远程连接服务器出现身份验证错误,又找不到加密Oracle修正

    今天想用远程桌面连接登录服务器,结果,弹出一个错误的提示框:发生身份验证错误,要求的函数不受支持. 然后在网上找了相关的教程,基本上所有的方法都是如下所示: 策略路径:"计算机配置" ...

  5. 我是怎么知道 PTHREAD_MUTEX_INITIALIZER 是什么鬼东西的 ??

    很简单 写这么几句代码 1 #include <pthread.h> 2 3 PTHREAD_MUTEX_INITIALIZER cpp 一解析就出来了 1714 # 238 " ...

  6. [物理学与PDEs]第1章第6节 电磁场的标势与矢势 6.3 例 --- 电偶极辐射

    1. 偶极子: 相距为 $l$, 带电量分别为 $\pm q$ 的一对电荷组成的系统. 称 $$\bex {\bf m}=q{\bf l} \eex$$ 为电偶极矩, 其中 ${\bf l}$ 为 $ ...

  7. oracle数据库驱动(ojdbc)

    第1部分 Q:为什么oralce的jdbc驱动,在maven上搜索到把pom配置复制到pom.xml里进行引用的时候会报错? ANS:虽然能在maven仓库里搜索到,但貌似不能用,原因是oracle是 ...

  8. centos7中nfs文件系统的使用

    需求: file01:1.1.1.1(内网ip 172.20.103.212),file02:2.2.2.2(内网ip 172.20.103.211) 这两台机器的 /dev/mapper/myvg- ...

  9. Lnmp下pureftpd新建FTP账户权限不足解决方法

    解决办法:  登录服务器.执行以下命令 chattr -i /home/wwwroot/default/.user.ini chown www:www -R /home/wwwroot/你的lnmp安 ...

  10. 代码中三种特殊注释——TODO、FIXME、XXX

    在eclipse中,TODO.FIXME和XXX都会被eclipse的task视图所收集.在项目发布前,检查一下task视图是一个很好的习惯.进入window→show view→Other→输入ta ...