洛谷 P4315 月下“毛景树”
洛谷 P4315 月下“毛景树”
题目描述
毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。
爬啊爬爬啊爬毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果 “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:
- Change k w:将第k条树枝上毛毛果的个数改变为w个。
- Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。
- Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:
- Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
输入格式
第一行一个正整数N。
接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。
输出格式
对于毛毛虫的每个询问操作,输出一个答案。
题解:
边转点是这道题唯一可以称得上难点的点。
然后就是裸的树剖架线段树。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const int N = 100100;
int ls(int x) {return x << 1;}
int rs(int x) {return x << 1 | 1;}
int n , cnt;
int u[N] , v[N] , w[N] , dep[N] , size[N] , fa[N] , top[N] , hs[N] , a[N] , son[N] , head[N] , dfn[N] , id[N];
int maxn[N << 2] , tag[N << 2] , lazy[N << 2];
char s[10];
struct Edge
{
int to , dis , nxt;
}e[N << 1];
void add(int from,int to,int dis)
{
e[++cnt] = (Edge){to,dis,head[from]};
head[from] = cnt;
}
void get_tree(int now)
{
size[now] = 1;
for(int i = head[now];i;i = e[i].nxt)
{
int to = e[i].to;
if(dep[to]) continue;
a[to] = e[i].dis;
dep[to] = dep[now] + 1;
fa[to] = now;
get_tree(to);
size[now] += size[to];
if(size[to] > size[hs[now]]) hs[now] = to;
}
}
void dfs(int now,int topfa)
{
dfn[now] = ++cnt;
id[cnt] = now;
top[now] = topfa;
if(hs[now]) dfs(hs[now],topfa);
for(int i = head[now];i;i = e[i].nxt)
{
int to = e[i].to;
if(to == fa[now] || to == hs[now]) continue;
dfs(to,to);
}
}
void build(int p,int l,int r)
{
if(l == r)
{
maxn[p] = a[id[l]];
return ;
}
int mid = (l + r) >> 1;
build(ls(p),l,mid);
build(rs(p),mid+1,r);
maxn[p] = max(maxn[ls(p)],maxn[rs(p)]);
}
void push_down(int p,int l,int r)
{
if(lazy[p] >= 0)
{
tag[ls(p)] = tag[rs(p)] = 0;
maxn[ls(p)] = maxn[rs(p)] = lazy[ls(p)] = lazy[rs(p)] = lazy[p];
lazy[p] = -1;
}
if(tag[p])
{
tag[ls(p)] += tag[p];
tag[rs(p)] += tag[p];
maxn[ls(p)] += tag[p];
maxn[rs(p)] += tag[p];
tag[p] = 0;
}
}
int query_max(int p,int l,int r,int x,int y)
{
if(x <= l && r <= y) return maxn[p];
int mid = (l + r) >> 1 , res = 0;
push_down(p,l,r);
if(x <= mid) res = max(res,query_max(ls(p),l,mid,x,y));
if(y > mid) res = max(res,query_max(rs(p),mid+1,r,x,y));
return res;
}
int sec_max(int x,int y)
{
int res = 0;
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x,y);
res = max(res , query_max(1,1,n,dfn[top[x]],dfn[x]));
x = fa[top[x]];
}
if(dep[x] < dep[y]) swap(x,y);
if(dfn[y] < dfn[x]) res = max(res,query_max(1,1,n,dfn[y]+1,dfn[x]));
return res;
}
void chenge_add(int p,int l,int r,int x,int y,int k)
{
if(x <= l && r <= y)
{
tag[p] += k;
maxn[p] += k;
return ;
}
int mid = (l + r) >> 1;
push_down(p,l,r);
if(x <= mid) chenge_add(ls(p),l,mid,x,y,k);
if(y > mid) chenge_add(rs(p),mid+1,r,x,y,k);
maxn[p] = max(maxn[ls(p)],maxn[rs(p)]);
}
void sec_add(int x,int y,int z)
{
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x,y);
chenge_add(1,1,n,dfn[top[x]],dfn[x],z);
x = fa[top[x]];
}
if(dep[x] < dep[y]) swap(x,y);
if(dfn[y] < dfn[x]) chenge_add(1,1,n,dfn[y]+1,dfn[x],z);
}
void chenge_cover(int p,int l,int r,int x,int y,int k)
{
if(x <= l && r <= y)
{
maxn[p] = k;
tag[p] = 0;
lazy[p] = k;
return ;
}
int mid = (l + r) >> 1;
push_down(p,l,r);
if(x <= mid) chenge_cover(ls(p),l,mid,x,y,k);
if(y > mid) chenge_cover(rs(p),mid+1,r,x,y,k);
maxn[p] = max(maxn[ls(p)],maxn[rs(p)]);
}
void sec_cover(int x,int y,int z)
{
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x,y);
chenge_cover(1,1,n,dfn[top[x]],dfn[x],z);
x = fa[top[x]];
}
if(dep[x] < dep[y]) swap(x,y);
if(dfn[y] < dfn[x]) chenge_cover(1,1,n,dfn[y]+1,dfn[x],z);
}
void chenge_(int p,int l,int r,int x,int k)
{
if(l == r)
{
maxn[p] = k;
tag[p] = 0;
lazy[p] = k;
return ;
}
int mid = (l + r) >> 1;
push_down(p,l,r);
if(x <= mid) chenge_(ls(p),l,mid,x,k);
else chenge_(rs(p),mid+1,r,x,k);
maxn[p] = max(maxn[ls(p)],maxn[rs(p)]);
}
int main()
{
memset(lazy,-1,sizeof lazy);
scanf("%d",&n);
for(int i = 1;i < n;i ++)
{
scanf("%d%d%d",&u[i],&v[i],&w[i]);
add(u[i],v[i],w[i]); add(v[i],u[i],w[i]);
}
cnt = 0; dep[1] = 1;
get_tree(1);
dfs(1,1);
build(1,1,n);
for(int i = 1;i < n;i ++)
{
if(fa[u[i]] == v[i]) son[i] = u[i];
else son[i] = v[i];
}
while(1)
{
int x , y , z;
scanf("%s",s);
if(s[0] == 'S')
break;
if(s[0] == 'M')
{
scanf("%d%d",&x,&y);
printf("%d\n",sec_max(x,y));
}
else if(s[0] == 'A')
{
scanf("%d%d%d",&x,&y,&z);
sec_add(x,y,z);
}
else if(s[1] == 'o')
{
scanf("%d%d%d",&x,&y,&z);
sec_cover(x,y,z);
}
else
{
scanf("%d%d",&x,&y);
chenge_(1,1,n,dfn[son[x]],y);
}
}
return 0;
}