P4315 月下“毛景树” (树链剖分+边剖分+区间覆盖+区间加+区间最大值)
题目链接:https://www.luogu.org/problem/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之间树枝上毛毛果个数最多有多少个。
解题思路:一道边权树剖题,代码很长,调试起来还是有点复杂。
注意一下几点:
1.可以把边权转化为点权,因为每一个孩子节点通向父节点的边是唯一的,所以可以将每个边的边权转到边所连的孩子节点上(可在树剖的第一个dfs中完成)
2.修改一条链上的权值时,要注意链两端的点的lca不能够被修改,因为lca所对应的边权不在这一条链上。
3.Change 操作是修改第k条树枝,k为读入的顺序,而树的存边是双向的,所以要将读入的k乘以二在进行后面的操作。
4.下推标记的时候如果有覆盖标记不要忘了清除加的标记。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=;
int tot,cnt,head[maxn],n,m,v[maxn];
ll tree[maxn*],lazy[maxn*],cov[maxn*];
int d[maxn],size[maxn],son[maxn],id[maxn],rk[maxn],fa[maxn],top[maxn];
//cov为覆盖标记,lazy为累加标记
struct Edge{
int u,v,w,next;
}edge[maxn<<];
void add(int u,int v,int w){
edge[++tot].v=v;
edge[tot].u=u;
edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot;
}
void dfs1(int u,int pre){
d[u]=d[pre]+;
fa[u]=pre;
size[u]=;
for(int i=head[u];i!=-;i=edge[i].next){
int vv=edge[i].v;
if(vv!=pre){
dfs1(vv,u);
size[u]+=size[vv];
v[vv]=edge[i].w; //边权转为点权
if(size[son[u]]<size[vv]) son[u]=vv;
}
}
}
void dfs2(int u,int tp){
top[u]=tp,id[u]=++cnt,rk[cnt]=u;
if(son[u]) dfs2(son[u],tp);
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].v;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
void pushup(int rt){
tree[rt]=max(tree[rt<<],tree[rt<<|]);
}
void pushdown(int l,int r,int rt){
if(cov[rt]!=-){
cov[rt<<]=cov[rt<<|]=cov[rt];
tree[rt<<]=tree[rt<<|]=cov[rt];
lazy[rt<<]=lazy[rt<<|]=; //将孩子节点的lazy标记清0
cov[rt]=-;
}
if(lazy[rt]){
tree[rt<<]=tree[rt<<]+lazy[rt];
tree[rt<<|]=tree[rt<<|]+lazy[rt];
lazy[rt<<]+=lazy[rt];
lazy[rt<<|]+=lazy[rt];
lazy[rt]=;
}
}
void build(int l,int r,int rt){
lazy[rt]=;
cov[rt]=-;
if(l==r){
tree[rt]=v[rk[l]];
return;
}
int mid=l+r>>;
build(l,mid,rt<<);
build(mid+,r,rt<<|);
pushup(rt);
}
void update1(int L,int R,int val,int l,int r,int rt){ //区间Cover和Change
if(L<=l&&R>=r){
tree[rt]=val;
cov[rt]=val;
lazy[rt]=; //将lazy标记清0
return;
}
int mid=l+r>>;
pushdown(mid-l+,r-mid,rt);
if(mid>=L) update1(L,R,val,l,mid,rt<<);
if(mid<R) update1(L,R,val,mid+,r,rt<<|);
pushup(rt);
}
void update2(int L,int R,int val,int l,int r,int rt){ //区间Add
if(L<=l&&R>=r){
tree[rt]+=val;
lazy[rt]+=val;
return;
}
int mid=l+r>>;
pushdown(mid-l+,r-mid,rt);
if(mid>=L) update2(L,R,val,l,mid,rt<<);
if(mid<R) update2(L,R,val,mid+,r,rt<<|);
pushup(rt);
}
ll query(int L,int R,int l,int r,int rt){ //区间求Max
if(L<=l&&R>=r) return tree[rt];
int mid=l+r>>; ll res=;
pushdown(mid-l+,r-mid,rt);
if(mid>=L) res=max(res,query(L,R,l,mid,rt<<));
if(mid<R) res=max(res,query(L,R,mid+,r,rt<<|));
return res;
}
void updates1(int x,int y,int val){ //Cover
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
update1(id[top[x]],id[x],val,,n,);
x=fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
update1(id[x]+,id[y],val,,n,); //不能更新lca所以是id[x]+1
}
void updates2(int x,int y,int val){ //Add
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
update2(id[top[x]],id[x],val,,n,);
x=fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
update2(id[x]+,id[y],val,,n,); //不能更新lca所以是id[x]+1
}
ll ask(int x,int y){ //求Max
ll res=;
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
res=max(res,query(id[top[x]],id[x],,n,));
x=fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
res=max(res,query(id[x]+,id[y],,n,));
return res;
}
int main(){
scanf("%d",&n);
memset(head,-,sizeof(head));
cnt=,tot=;
for(int i=;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w); add(v,u,w);
}
dfs1(,),dfs2(,);
build(,n,);
while(true){
char op[];
int x,l,r,rt,val;
scanf("%s",op);
if(op[]=='t') break;
if(op[]=='h'){
scanf("%d%d",&x,&val); //因为是无向边,所以x*2表示的就是第x条边
x=d[edge[x*].u]>d[edge[x*].v]?edge[x*].u:edge[x*].v;
update1(id[x],id[x],val,,n,); //Change操作
} else if(op[]=='o'){
scanf("%d%d%d",&l,&r,&val);
updates1(l,r,val); //Cover操作
} else if(op[]=='d'){
scanf("%d%d%d",&l,&r,&val);
updates2(l,r,val); //Add操作
} else if(op[]=='a'){
scanf("%d%d",&l,&r);
printf("%lld\n",ask(l,r)); //Max操作
}
}
return ;
}
P4315 月下“毛景树” (树链剖分+边剖分+区间覆盖+区间加+区间最大值)的更多相关文章
- P4315 月下“毛景树”(树链剖分)
P4315 月下"毛景树"(树链剖分) 题面 简述: 边权转点权(在dfs1处转换) 把一条边权赋值在深度更深的上 需要实现对单边权的染色 , 路径边权的染色 , 路径边权的增加 ...
- P4315 月下“毛景树”
P4315 月下"毛景树" 题目描述 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里. 爬啊爬~爬啊爬 ...
- 洛谷P4315 月下“毛景树”(树剖+线段树)
传送门 woc这该死的码农题…… 把每一条边转化为它连接的两点中深度较深的那一个,然后就可以用树剖+线段树对路径进行修改了 然后顺便注意在上面这种转化之后,树剖的时候不能搞$LCA$ 然后是几个注意点 ...
- 洛谷P4315 月下“毛景树”
题目描述 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里. 爬啊爬~爬啊爬毛毛虫爬到了一颗小小的"毛景树&quo ...
- P4315 月下“毛景树”[树剖]
题目描述 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里. 爬啊爬~爬啊爬毛毛虫爬到了一颗小小的"毛景树&quo ...
- [洛谷P4315] 月下”毛景“树
题目链接: 点我 题目分析: 树剖.将边权下放到下方点上(为什么要选深度更深的点?一个父亲可能对应多个儿子,但一个儿子只有一个父亲,即可以保证每个点只保存一条边权)成为经典点权+树剖裸题 注意链计算时 ...
- BZOJ 1984: 月下“毛景树” [树链剖分 边权]
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1728 Solved: 531[Submit][Status][Discu ...
- 【BZOJ-1984】月下“毛景树” 树链剖分
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1314 Solved: 416[Submit][Status][Discu ...
- Bzoj 1984: 月下“毛景树” 树链剖分
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1282 Solved: 410[Submit][Status][Discu ...
随机推荐
- mybatis 注解方式插入,主键由uuid函数生成
@SelectKey(keyProperty = "record.id", resultType = String.class, before = true, statement ...
- 微信小程序 API 网络(ajax)
网络 API 类似于 ajax 向服务器请求网络地址,唯一不同的是这个请求有很多的规则,且必须向服务器上请求,不能在本地请求 网络 发送请求: wx.request() 发起https网络请求 参数: ...
- leetcode-easy-array-48. Rotate Image-NO
mycode 思路:第m行要变到 - 1- m 列 ,但是没有再想一步即列变为行,这样每一个位置的变换方式就出来了 难点:如何不使用额外空间呢? 参考: 思路:找到矩阵旋转和转置之间的联系,转置是可以 ...
- [C#菜鸟]C# Hook (一)
转过来的文章,出处已经不知道了,但只这篇步骤比较清晰,就贴出来了. 一.写在最前 本文的内容只想以最通俗的语言说明钩子的使用方法,具体到钩子的详细介绍可以参照下面的网址: http://www.mic ...
- 2018 icpc 青岛
https://zoj.pintia.cn/contests/91827364639/problems C 要把这两个二进制串变为相同,需要先看哪些位置不同,设为数组c,某位为1则两位不同. 分1形成 ...
- spss中如何处理极端值、错误值
spss中如何处理极端值.错误值 spss中录入数据以后,第一步不是去分析数据,而是要检验数据是不是有录入错误的,是不是有不合常理的数据,今天我们要做一个描述性统计,进而查看哪些数据是不合理的.下面是 ...
- oracle data guard --理论知识回顾01
之前搭建了rac到单实例的dg环境,最近又在windows下搭建了dg,这一篇关于dg的一些理论知识回顾 官方文档 https://docs.oracle.com/cd/E11882_01/nav/p ...
- 【BW系列】SAP BW实时抽取ECC数据的实现
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[BW系列]SAP BW实时抽取ECC数据的实现 ...
- ionic3遇到的刷新页面服务器关闭的问题
这几天为了写毕设,需要使用Ionic写手机客户端,遇到一些奇怪的问题,具体问题就是启动使用ionic serve启动服务器之后只要一刷新界面就会导致服务器关闭,报的错误如下: events.js:13 ...
- .net core 学习小结之 配置介绍(config)以及热更新
命令行的配置 var settings = new Dictionary<string, string>{ { "name","cyao"}, {& ...