[luogu4315] 月下“毛景树”
传送门
这题真棒!
首先是这题是边权题,为了方便处理,化为点权。可一条边有两点点啊,用哪个存权值好呢?当然是儿子啦!因为一个儿子唯一对应一个连着父亲的边。
然后这题对于线段树涉及到区间最值查询、区间修改、区间加、单点修改,我很偷懒地把单点修改弄成区间修改了。
那么运算优先级问题:区间覆盖优于区间加,因为一旦有一个区间覆盖出现,之前所有的区间加都可以情空,处理起来很方便。
那么就是剖分的问题了:你会发现路径上的LCA存的值,是属于LCA和它父亲的边,一定不在这条路径上,所以不可以访问。最初考虑求出LCA,然后单点修改,区间操作,然后再单点修改。但是这样很麻烦啊……厚颜无耻地看了题解……你会发现我们在剖分的过程中,最后一定会跳到同一条重链上,深度小的就是LCA!!!那么我们可以怎么不去访问它呢?只需要把它的dfs序+1即可,因为这是一条重链,+1后就是它的重儿子!还可以保证区间不会断!
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 100005
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mid ((l+r)>>1)struct table {int v,w,next;
}G[MAXN<<1];struct edge {int u,v,w;
}E[MAXN];int head[MAXN];int dfn[MAXN],top[MAXN],val[MAXN];
int size[MAXN],son[MAXN],son_w[MAXN],d[MAXN],fa[MAXN];int seg[MAXN<<2],tag[MAXN<<2],sum[MAXN<<2];
int N,tot = 0,num = 0;inline void add(int u,int v,int w) {G[++tot].v = v;G[tot].w = w;G[tot].next = head[u];head[u] = tot;
}inline void pushup(int rt) {seg[rt] = std::max(seg[lson],seg[rson]);
}void Build(int rt,int l,int r) {tag[rt] = -1;sum[rt] = 0;if(l==r) {seg[rt] = val[l];return;}Build(lson,l,mid);Build(rson,mid+1,r);pushup(rt);
}inline void pushdown(int rt) {if(tag[rt]!=-1) {sum[lson] = sum[rson] = 0;tag[lson] = tag[rson] = seg[lson] = seg[rson] = tag[rt];tag[rt] = -1;}sum[lson] += sum[rt];sum[rson] += sum[rt];seg[lson] += sum[rt];seg[rson] += sum[rt];sum[rt] = 0;
}void sum_update(int C,int L,int R,int rt,int l,int r) {if(L<=l&&R>=r) {seg[rt] += C;sum[rt] += C;return;}if(L>r||R<l) return;pushdown(rt);if(L<=mid) sum_update(C,L,R,lson,l,mid);if(r>mid) sum_update(C,L,R,rson,mid+1,r);pushup(rt);
}void tag_update(int C,int L,int R,int rt,int l,int r) {if(L<=l&&R>=r) {seg[rt] = C;sum[rt] = 0;tag[rt] = C;return;}if(L>r||R<l) return;pushdown(rt);if(L<=mid) tag_update(C,L,R,lson,l,mid);if(r>mid) tag_update(C,L,R,rson,mid+1,r);pushup(rt);
}int query(int L,int R,int rt,int l,int r) {if(L<=l&&R>=r) return seg[rt];if(L>r||R<l) return 0;pushdown(rt);int maxx = 0;if(L<=mid) maxx = query(L,R,lson,l,mid);if(r>mid) maxx = std::max(maxx,query(L,R,rson,mid+1,r));pushup(rt);return maxx;
}void dfs1(int u,int father) {d[u] = d[father] + 1; size[u] = 1;son[u] = 0; son_w[u] = 0; fa[u] = father;for(int i=head[u];i;i=G[i].next) {int v = G[i].v; if(v==father) continue;dfs1(v,u); size[u] += size[v];if(size[son[u]]<size[v]) son[u] = v,son_w[u] = G[i].w;}
}void dfs2(int u,int tp,int w) {dfn[u] = ++num; val[num] = w; top[u] = tp;if(son[u]) dfs2(son[u],tp,son_w[u]);for(int i=head[u];i;i=G[i].next) {int v = G[i].v;if(v==fa[u]||v==son[u]) continue;dfs2(v,v,G[i].w);}
}inline void chain_sum_update(int u,int v,int w) {while(top[u]!=top[v]) {if(d[top[u]]<d[top[v]]) std::swap(u,v);sum_update(w,dfn[top[u]],dfn[u],1,1,N);u = fa[top[u]];}if(d[u]>d[v]) std::swap(u,v);sum_update(w,dfn[u]+1,dfn[v],1,1,N);
}inline void chain_tag_update(int u,int v,int w) {while(top[u]!=top[v]) {if(d[top[u]]<d[top[v]]) std::swap(u,v);tag_update(w,dfn[top[u]],dfn[u],1,1,N);u = fa[top[u]];}if(d[u]>d[v]) std::swap(u,v);tag_update(w,dfn[u]+1,dfn[v],1,1,N);
}inline int chain_query(int u,int v) {int maxx = 0;while(top[u]!=top[v]) {if(d[top[u]]<d[top[v]]) std::swap(u,v);maxx = std::max(maxx,query(dfn[top[u]],dfn[u],1,1,N));u = fa[top[u]];}if(d[u]>d[v]) std::swap(u,v);maxx = std::max(maxx,query(dfn[u]+1,dfn[v],1,1,N));return maxx;
}inline int get_opt() {char ch = getchar();int opt = 0;while(ch<'A'||ch>'Z') ch = getchar();if(ch=='M') opt = 1;else if(ch=='A') opt = 2;else if(ch=='C') {ch = getchar();if(ch=='h') opt = 3;else opt = 4;}else if(ch=='S') opt = 0;while(ch!=' '&&ch!='\n'&&ch!=EOF) ch = getchar();return opt;
}int main() {int u,v,w;scanf("%d",&N);for(int i=1;i<N;++i) {scanf("%d%d%d",&u,&v,&w);E[i] = (edge){u,v};add(u,v,w); add(v,u,w);}d[0] = size[0] = 0;dfs1(1,0); dfs2(1,0,0);Build(1,1,N);int opt;while((opt = get_opt())!=0) {if(opt==1) {scanf("%d%d",&u,&v);printf("%d\n",chain_query(u,v));}else if(opt==2) {scanf("%d%d%d",&u,&v,&w);chain_sum_update(u,v,w);}else if(opt==3) {scanf("%d%d",&u,&w);chain_tag_update(E[u].u,E[u].v,w);}else if(opt==4) {scanf("%d%d%d",&u,&v,&w);chain_tag_update(u,v,w);}}return 0;
}
转载于:https://www.cnblogs.com/Neworld2002/p/10016968.html
[luogu4315] 月下“毛景树”相关推荐
- 树剖+线段树||树链剖分||BZOJ1984||Luogu4315||月下“毛景树”
题面:月下"毛景树" 题解:是道很裸的树剖,但处理的细节有点多(其实是自己线段树没学好).用一个Dfs把边权下移到点权,用E数组记录哪些边被用到了:前三个更新的操作都可以合并起来, ...
- [bzoj1984]月下“毛景树” 树链剖分
1984: 月下"毛景树" Time Limit: 20 Sec Memory Limit: 64 MB [Submit][Status][Discuss] Descriptio ...
- BZOJ1984: 月下“毛景树”
BZOJ 1984: 月下"毛景树" Time Limit: 20 Sec Memory Limit: 64 MB Submit: 1583 Solved: 500 [Subm ...
- P4315 月下“毛景树” (树链剖分)
题目链接: P4315 月下"毛景树" 大致题意 给定一棵由nnn个节点的树, 由n−1n - 1n−1带权边构成. 有如下444种操作: Change k c: 把第kkk条边的 ...
- 洛谷P4315 月下“毛景树” 题解
洛谷P4315 月下"毛景树" 题解 题目链接:P4315 月下"毛景树" 题意:请维护一个数据结构,支持 改第 kkk 条边的边权 结点 uuu 到 vvv ...
- [BZOJ1984] 月下“毛景树”
Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的" ...
- 洛谷P4315 月下“毛景树”
题目描述 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里. 爬啊爬~爬啊爬毛毛虫爬到了一颗小小的"毛景树&quo ...
- bzoj 1984: 月下“毛景树” 线段树+树链剖分
题意 给出一棵n个节点的树,每条边都有权值,要求资瓷以下操作: Max x y表示查询x到y之间的最大权值 Cover x y z表示把x到y的权值赋为z Change x y表示把第x条边的权值变成 ...
- 【洛谷P4315】月下“毛景树”(树链剖分)
这是一道毒瘤题. 首先题目中给的是边权而不是点权,但是我们把边权移到点上就行了 但是要注意,之后我们修改u,v两点之间的路径时,就不要修改他们的lca,以及当要修改单边的时候,把边的编号*2(因为是双 ...
- 洛谷 P4315 月下“毛景树”(边树剖)
题目不算难,但是代码量需要控制 主要说一下线段树上的操作,因为有两个相关的区间操作标记,应该先覆盖后增加,因为覆盖操作会影响增加操作 const int N=1e5+5;int n,m;int i,j ...
最新文章
- ExtJS grid简单应用之 展示JSON数据
- NLP之WordCloud:基于jieba+matplotlib库对一段文本生成词云图~~情人节最好的礼物(给你一张过去的词云图,看看那时我们的爱情)
- 解析网络诊断利器SreCli-Net
- sqlite数据类型、关键词及创建、修改、删除数据表
- ArcGIS10.6中,在3D分析工具中创建视线之后,怎么将其删除?
- 销货清单数据_2020年8月数据科学阅读清单
- pc-bsd安装教程_桌面用户的BSD:PC-BSD的回顾
- 职责链模式在开发中的应用
- php git server,server.php
- java 序列化快捷键_IntelliJ IDEA生成 Serializable序列化UID的快捷键
- Hive基本操作入门
- 如何迅速的找到合适的开发者?
- 浅谈几种常见 RAID 的异同
- mysql sql语句执行到一半会怎么样?
- 【机器学习】主成分分析 (PCA)、无监督特征提取
- 趋势科技防毒墙网络版—OfficeScan
- 产品经理入门知识梳理(含思维导图
- 如何修复iTunes中未显示的iPhone或iPad
- 探索Bitmap使用姿势
- 根据出生年月日计算出生了多少年,多少月,多少天