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 ...
随机推荐
- How jQuery UI Works
https://learn.jquery.com/jquery-ui/how-jquery-ui-works/ jQuery UI contains many widgets that maintai ...
- 洛谷P1198 [JSOI2008]最大数(单点修改,区间查询)
洛谷P1198 [JSOI2008]最大数 简单的线段树单点问题. 问题:读入A和Q时,按照读入一个字符会MLE,换成读入字符串就可以了. #include<bits/stdc++.h> ...
- hdu6599 I Love Palindrome String
由样例可知,题目中求的回文串数量,其实是本质不同的回文串数量,这个可以直接用回文树来做. 考虑前半段是回文串这个限制,这个东西回文树不好做,可以再套一个马拉车,然后记录一下插入到回文树的节点中最后一个 ...
- 阶段3 1.Mybatis_09.Mybatis的多表操作_9 mybatis多对多操作-查询用户获取用户所包含的角色信息
sql语句以user作为主表 用户的全部信息,以为用户下的角色的.并不是所有的用户都有角色,有角色的就带角色.没角色的就为null 首先修改实体类 定义List<Role> 生成gette ...
- fiddler之入门(安装配置)
在工作中常常需要进行数据的抓包和发包,此时就可以用到fiddler这个工具了. fiddler是一个http协议调试代理工具,通过http代理,让数据从其通过,来坚挺本地计算机与访问网络之间的所有ht ...
- 【奇技淫巧】linux 定时任务 crontab 反弹 shell
日期:2018-11-26 13:47:34 介绍:如何使用定时任务来反弹 shell? 0x01. 基本命令 参数 -e:编辑该用户的计时器设置: -l:列出该用户的计时器设置: -r:删除该用户的 ...
- 《Using Databases with Python》Week3 Data Models and Relational SQL 课堂笔记
Coursera课程<Using Databases with Python> 密歇根大学 Week3 Data Models and Relational SQL 15.4 Design ...
- 深入理解java:2.2. 同步锁Synchronized及其实现原理
同步的基本思想 为了保证共享数据在同一时刻只被一个线程使用,我们有一种很简单的实现思想,就是 在共享数据里保存一个锁 ,当没有线程访问时,锁是空的. 当有第一个线程访问时,就 在锁里保存这个线程的标识 ...
- 删除MicrosoftOffice2016的扫尾工作
因为用到一些画流程图之类的工具,想到以前用的Visio挺好用的,就找来安装一下,结果因为装了Microsoft Office2016在安装时报错不断,先说下网上的帖子:用OfficeDeploymen ...
- vue使用笔记二
es6\es2015特性http://lib.csdn.net/article/reactnative/58021?knId=1405 使用express-generator初始化你的项目目录http ...