题目链接:##

点我

题目分析:##

树剖。将边权下放到下方点上(为什么要选深度更深的点?一个父亲可能对应多个儿子,但一个儿子只有一个父亲,即可以保证每个点只保存一条边权)成为经典点权+树剖裸题

注意链计算时不能把LCA算进去,其余细节较多,具体见代码。

代码:##

#include<bits/stdc++.h>
#define N (100000 + 5)
#define inf (1000000000+7)
using namespace std;
inline int read() {
int cnt = 0, f = 1; char c;
c = getchar();
while(!isdigit(c)) {
if (c == '-') f = -f;
c = getchar();
}
while(isdigit(c)) {
cnt = cnt * 10 + c - '0';
c = getchar();
}
return cnt * f;
}
int nxt[N * 2], first[N * 2], to[N * 2], w[N * 2], a[N], tot;
int father[N], top[N], siz[N], dep[N], son[N], num[N], id[N], idx;
int n, u, v, W, k;
char opr[20];
struct node{
int l, r;
long long cov, add, gmax;
#define l(p) tree[p].l
#define r(p) tree[p].r
#define cov(p) tree[p].cov
#define add(p) tree[p].add
#define gmax(p) tree[p].gmax
} tree[N * 4]; struct edge{
int u; int v;
}e[N * 2]; void Add(int x, int y, int z) {
nxt[++tot] = first[x];
first[x] = tot;
to[tot] = y;
w[tot] = z;
} void dfs1(int cur, int fa) {
father[cur] = fa; siz[cur] = 1; dep[cur] = dep[fa] + 1;
for (register int i = first[cur]; i; i = nxt[i]) {
int v = to[i];
if(v != fa) {
a[v] = w[i];
dfs1(v, cur);
siz[cur] += siz[v];
if(siz[son[cur]] < siz[v]) son[cur] = v;
}
}
} void dfs2(int cur, int tp) {
top[cur] = tp; num[cur] = ++idx; id[idx] = cur;
if (son[cur]) dfs2(son[cur], tp);
for (register int i = first[cur]; i; i = nxt[i]) {
int v = to[i];
if (!num[v]) dfs2(v, v);
}
} void pushup(int p) {
gmax(p) = max(gmax(p << 1), gmax(p << 1 | 1));
}
void pushcover(int p, int v){cov(p) = v; add(p) = 0; gmax(p) = v;}
void pushadd(int p,int v){ add(p)+=v; gmax(p)+=v;}
void pushdown(int p) {
if (cov(p) >= 0) {
pushcover(p<<1, cov(p)); pushcover(p<<1|1, cov(p)); cov(p) = -1;
}
if (add(p)) {
pushadd(p<<1, add(p)); pushadd(p<<1|1, add(p)); add(p) = 0;
}
} void build_tree(int p, int l, int r) {
l(p) = l; r(p) = r; cov(p) = -1;
if(l == r) {
gmax(p) = a[id[l]];
// cout<<l<<" "<<r<<" "<<gmax(p)<<endl;
return;
}
int mid = (l + r) >> 1;
build_tree(p << 1, l, mid);
build_tree(p << 1 | 1, mid + 1, r);
pushup(p);
}
void debug(int u,int l,int r){
if(l==r){
cout<<id[l]<<" "<<gmax(u)<<endl;return;
}int mid=(l+r)>>1;
debug(u*2,l,mid);debug(u*2+1,mid+1,r);
}
void Cover(int p, int l, int r, int d) {
if (l > r) return;
if (l <= l(p) && r >= r(p)) {
pushcover(p, d);
return;
}
pushdown(p);
int mid = (l(p) + r(p)) >> 1;
if (l <= mid) Cover(p << 1, l, r, d);
if (r > mid) Cover(p << 1 | 1, l, r, d);
pushup(p);
} void Modify(int p, int l, int r, int d) {
if (l > r) return;
if (l <= l(p) && r >= r(p)) {
// if(cov(p) >= 0) {
// cov(p) += d;
// gmax(p) += d;
// } else {
// pushadd(p, d);
// }
pushadd(p, d);
return;
}
pushdown(p);
int mid = (l(p) + r(p)) >> 1;
if (l <= mid) Modify(p << 1, l, r, d);
if (r > mid) Modify(p << 1 | 1, l, r, d);
pushup(p);
} long long query(int p, int l, int r) {
// cout<<p<<" "<<l(p)<<" "<<r(p)<<endl;
if (l <= l(p) && r >= r(p)) return gmax(p);
int mid = (l(p) + r(p)) >> 1;
pushdown(p);
//cout<<p<<endl;
long long val = -inf;
if (l <= mid) val = max (val, query(p << 1, l, r));
if (r > mid) val = max(val, query(p << 1 | 1, l, r));
return val;
} void chain_cover(int u, int v, int d) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
Cover(1, num[top[u]], num[u], d);
u = father[top[u]];
}
if (dep[u] < dep[v]) swap(u, v);
// if (u == v) Cover(1, num[v], num[u], d);
Cover(1, num[v] + 1, num[u], d);
} void chain_modify(int u, int v, int d) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
Modify(1, num[top[u]], num[u], d);
u = father[top[u]];
}
if (dep[u] < dep[v]) swap(u, v);
// if (u == v) Modify(1, num[v], num[u], d);
Modify(1, num[v] + 1, num[u], d);
} long long chain_query(int u, int v) {
long long ans = -inf;
while (top[u] != top[v]) {//cout<<u<<endl;
// cout<<top[u]<<" "<<top[v]<<endl;
if (dep[top[u]] < dep[top[v]]) swap(u, v);
// cout<<top[u]<<" "<<top[v]<<endl;
// cout<<num[top[u]]<<" "<<num[u]<<endl;
// cout<<query(1,num[top[u]],num[u])<<"###"<<endl;
ans = max(ans, query(1, num[top[u]], num[u]));//cout<<"#";
u = father[top[u]];
// cout<<ans<<endl;
}
if (dep[u] < dep[v]) swap(u, v);
ans = max(ans, query(1, num[v] + 1, num[u]));
return ans;
} void solve() {
n = read();
for (register int i = 1; i < n; i++) {
u = read(); v = read(); W = read();
e[i].u = u; e[i].v = v;
Add(u, v, W); Add(v, u, W);
}
dfs1(1, 0); dfs2(1, 1);
// for(int i=1;i<=n;i++)cout<<a[i]<<" ";cout<<endl;
// for(int i=1;i<=n;i++)cout<<id[i]<<" ";cout<<endl;
build_tree(1, 1, n);
// debug(1,1,n);
// cout<<"#"<<endl;
for (;;) {
scanf("%s", opr + 1);
if (opr[1] == 'M') {
u = read(); v = read();
printf("%lld\n", chain_query(u, v));
}
if (opr[1] == 'C') {
if (opr[2] == 'o') {
u = read(); v = read(); W = read();
chain_cover(u, v, W);
}
if (opr[2] == 'h') {
u = read(); W = read();
if (dep[e[u].u] < dep[e[u].v]) swap(e[u].u, e[u].v);
// cout<<"nmsl"<<e[u].u<<" "<<e[u].v<<endl;
// cout<<"##"<<num[e[u].u]<<"WWW"<<W<<endl;
// chain_cover(num[e[u].u], num[e[u].v], W);
Cover(1, num[e[u].u], num[e[u].u], W);
}
}
if (opr[1] == 'A') {
u = read(); v = read(); W = read();
chain_modify(u, v, W);
}
if (opr[1] == 'S') break;
// debug(1,1,n);cout<<endl;
}
return;
} int main() {
// freopen("input.in","r",stdin);
solve();
return 0;
}

[洛谷P4315] 月下”毛景“树的更多相关文章

  1. 洛谷P4315 月下“毛景树”

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

  2. 洛谷P4315 月下“毛景树”(树剖+线段树)

    传送门 woc这该死的码农题…… 把每一条边转化为它连接的两点中深度较深的那一个,然后就可以用树剖+线段树对路径进行修改了 然后顺便注意在上面这种转化之后,树剖的时候不能搞$LCA$ 然后是几个注意点 ...

  3. P4315 月下“毛景树”

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

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

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

  5. P4315 月下“毛景树” (树链剖分+边剖分+区间覆盖+区间加+区间最大值)

    题目链接:https://www.luogu.org/problem/P4315 题目大意: 有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的.但是这棵“毛景树”有着神奇的魔力 ...

  6. P4315 月下“毛景树”[树剖]

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

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

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

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

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

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

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

随机推荐

  1. css3线性渐变兼容

    火狐浏览器: background:-moz-linear-gradient(top, red, rgba(0, 0, 255, 0.5)); 谷歌: .l6{background: -webkit- ...

  2. spring2.5整合struts2

    首先第一步: 导入jar包: 我的做法: 导入你的基本使用的spring的jar包 和基本使用的struts2的jar包 然后struts2中有一个和spring整合的jar包一定要导入,不然会抛异常 ...

  3. hls协议(最清晰的讲解)

    今天来介绍一下HLS协议,这个协议是由苹果公司提出并推广开来的.来一段维基百科的定义. HTTP Live Streaming(缩写是HLS)是一个由苹果公司提出的基于HTTP的流媒体网络传输协议.是 ...

  4. 在线接口管理工具-eoapi

    为了方便和前端沟通,临时在局域网搭建了一个接口管理工具,查了一些资料都说eoapi不错,那就试了一下: 1.安装 要在服务器或者自己的电脑,准备web环境,Linux可以是Apache/nginx , ...

  5. C++中两个类相互包含引用问题

    在构造自己的类时,有可能会碰到两个类之间的相互引用问题,例如:定义了类A类B,A中使用了B定义的类型,B中也使用了A定义的类型 class A { int i; B b; } class B { in ...

  6. bzoj 2555 SubString —— 后缀自动机+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 建立后缀自动机,就可以直接加入新串了: 出现次数就是 Right 集合的大小,需要查询 ...

  7. JAVA操作cassandra数据库

    如果是maven项目,在pom.xml里加入依赖.不是的话下载相应的jar包放到lib目录下.这里驱动包的版本要和你cassandra的大版本一致.我这里cassandra的版本是最新的3.9,驱动是 ...

  8. ceph 删除了osd但是osd目录保存完整如何恢复

    1. 这里假设有一个osd被删除了 执行下列步骤删除: ceph osd out osd.0 service ceph stop osd.0 ceph osd crush remove osd.0 c ...

  9. openstack实现nova-api的HA

    1       实验环境 Openstack juno版本,一个controller(计算节点也在这个物理节点上)和一个网络节点network 使用haproxy作为代理软件 使用pacemaker作 ...

  10. 如何解决 Matlab 画图时中文显示乱码的问题?

    使用的是win10系统,从前几个月某一天,我的matlab的figure里的中文都变成了口口.很是郁闷,还以为是动到了什么配置引起的. 前几天更新了matlab 2018b,发现还有这个问题.就觉得不 ...