【Luogu】P3313旅行(树链剖分)
动态开点的树链剖分qwq。
跟小奇的花园一模一样,不做过多讲解。
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cstdlib>
#include<algorithm>
#define maxn 100010
#define mid ((l+r)>>1)
#define check(x) if(x==0) x=++tot;
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} struct Edge{
int next,to;
}edge[maxn*];
int head[maxn],num;
inline void add(int from,int to){
edge[++num]=(Edge){head[from],to};
head[from]=num;
} int dfn[maxn];
int back[maxn],cnt;
int sum[maxn*],tot;
int mav[maxn*];
int root[maxn];
int ls[maxn*];
int rs[maxn*];
int top[maxn];
int size[maxn];
int son[maxn];
int deep[maxn];
int father[maxn];
int d[maxn];
int q[maxn];
int n,m; void find(int x,int fa){
size[x]=;deep[x]=deep[fa]+;
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(to==fa) continue;
father[to]=x;
find(to,x);
size[x]+=size[to];
if(son[x]==||size[son[x]]<size[to]) son[x]=to;
}
} void unionn(int x,int Top){
dfn[x]=++cnt; back[cnt]=x;
top[x]=Top;
if(son[x]==) return;
unionn(son[x],Top);
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(to==father[x]||to==son[x]) continue;
unionn(to,to);
}
} inline void pushup(int rt){
sum[rt]=sum[ls[rt]]+sum[rs[rt]];
mav[rt]=max(mav[ls[rt]],mav[rs[rt]]);
} void update(int o,int num,int l,int r,int &rt){
check(rt);
if(l==r){
sum[rt]=num;
mav[rt]=num;
return;
}
if(o<=mid) update(o,num,l,mid,ls[rt]);
else update(o,num,mid+,r,rs[rt]);
pushup(rt);
return;
} int quemax(int from,int to,int l,int r,int &rt){
if(rt==) return ;
if(from<=l&&to>=r) return mav[rt];
int ans=;
if(from<=mid) ans=max(ans,quemax(from,to,l,mid,ls[rt]));
if(to>mid) ans=max(ans,quemax(from,to,mid+,r,rs[rt]));
return ans;
} int quesum(int from,int to,int l,int r,int &rt){
if(rt==) return ;
if(from<=l&&to>=r) return sum[rt];
int ans=;
if(from<=mid) ans+=quesum(from,to,l,mid,ls[rt]);
if(to>mid) ans+=quesum(from,to,mid+,r,rs[rt]);
return ans;
} int askmax(int from,int to,int val){
int ans=;
while(top[from]!=top[to]){
if(deep[top[from]]<deep[top[to]]) swap(from,to);
ans=max(ans,quemax(dfn[top[from]],dfn[from],,n,root[val]));
from=father[top[from]];
}
if(deep[from]>=deep[to]) swap(from,to);
ans=max(ans,quemax(dfn[from],dfn[to],,n,root[val]));
return ans;
} int asksum(int from,int to,int val){
int ans=;
while(top[from]!=top[to]){
if(deep[top[from]]<deep[top[to]]) swap(from,to);
ans+=quesum(dfn[top[from]],dfn[from],,n,root[val]);
from=father[top[from]];
}
if(deep[from]>=deep[to]) swap(from,to);
ans+=quesum(dfn[from],dfn[to],,n,root[val]);
return ans;
} void chancol(int pos,int val){
update(dfn[pos],,,n,root[q[pos]]);
update(dfn[pos],d[pos],,n,root[val]);
q[pos]=val;
} void channum(int pos,int val){
update(dfn[pos],val,,n,root[q[pos]]);
d[pos]=val;
} int main(){
n=read(),m=read();
for(int i=;i<=n;++i){
d[i]=read();q[i]=read();
}
for(int i=;i<n;++i){
int x=read(),y=read();
add(x,y);
add(y,x);
}
find(,);
unionn(,);
for(int i=;i<=n;++i) update(dfn[i],d[i],,n,root[q[i]]);
for(int i=;i<=m;++i){
char c[];
scanf("%s",c);
if(c[]=='C'){
if(c[]=='C'){
int x=read(),y=read();
chancol(x,y);
}
else{
int x=read(),y=read();
channum(x,y);
}
}
else if(c[]=='Q'){
if(c[]=='S'){
int x=read(),y=read();
printf("%d\n",asksum(x,y,q[x]));
}
else{
int x=read(),y=read();
printf("%d\n",askmax(x,y,q[x]));
}
}
}
return ;
}
https://www.luogu.org/problemnew/show/P3313
【Luogu】P3313旅行(树链剖分)的更多相关文章
- [luogu P3384] [模板]树链剖分
[luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...
- P3313 [SDOI2014]旅行——树链剖分+线段树(动态开点?)
P3313 [SDOI2014]旅行 一棵树,其中的点分类,点有权值,在一条链上找到一类点中的最大值或总和: 树链剖分把树变成链: 把每个宗教单开一个线段树,维护区间总和和最大值: 宗教很多,需要动态 ...
- 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)
题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...
- BZOJ 3531: [Sdoi2014]旅行 [树链剖分]
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1685 Solved: 751[Submit][Status] ...
- BZOJ3531:[SDOI2014]旅行(树链剖分)
Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...
- BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树
题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...
- cogs 186. [USACO Oct08] 牧场旅行 树链剖分 LCA
186. [USACO Oct08] 牧场旅行 ★★☆ 输入文件:pwalk.in 输出文件:pwalk.out 逐字节对比时间限制:1 s 内存限制:128 MB n个被自然地编号为 ...
- BZOJ 2157 旅行(树链剖分码农题)
写了5KB,1发AC... 题意:给出一颗树,支持5种操作. 1.修改某条边的权值.2.将u到v的经过的边的权值取负.3.求u到v的经过的边的权值总和.4.求u到v的经过的边的权值最大值.5.求u到v ...
- [BZOj4336][BJOI2015]骑士的旅行(树链剖分+线段树)
树链剖分,对每个叶子用multiset记录前K大士兵,其余节点通过从儿子归并维护前K大士兵.过于模板. #include<set> #include<cstdio> #incl ...
- BZOJ 3531 SDOI2014 旅行 树链剖分+线段树动态开点
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3531 题意概述: 给出一棵N个点的树,树上的每个结点有一个颜色和权值,支持以下四种操作: ...
随机推荐
- Linq语法学习_增删篇。
关键词: select from where in into join on equals orderby descending thenby Table<TEntity> Default ...
- cesium-大规模人群运动测试
环境:cesium1.57: 笔记本电脑:集成显卡+独显Navida 1060 测试内容:大规模人群运动(500人,可设置运动的路径),可行性及帧率 测试结果:21-23FPS,较为流畅:集显70%- ...
- Windows环境下使用Apache+mod
1.安装Python和Apache. 2.安装mod_wsgi后获得wsgi.so,并将wsgi.so放到Apache的modules文件夹下. 3.安装webpy. 4.打开httpd.conf(在 ...
- npm上发布包和删除已发布的npm包(https://www.npmjs.com/)
1.npm上发布自己写的包 2.删除已经发布的包 npm unpublish --force //强制删除,这个是撤销24小时发布的包,有些包发布久了,这个方法不会再管用了. npx force-un ...
- java第八次作业:课堂上发布的前5张图片(包括匿名对象、单例模式恶汉式、自动生成对象、args[]数组使用、静态关键字)
- cocos2dx for lua 摄像机移动
在cocos2dx中,我们想通过移动摄像机来做一些特殊处理,比如将摄像机聚焦在某个物体上,或者摄像机颤抖,摄像机原理观察sprite回收状况等等, 都需要通过相机移动来使用. cocos2dx中的摄像 ...
- iOS项目工程及目录结构
做过一些iOS的项目,不同项目的沉淀没有积累到一起,目录的管理都在后期随着人员的增加越来越混乱,因此在这里做一些梳理,希望达到两个目的. 一套相对通用的目录结构,作为后续项目的模版. 积累相应的基础库 ...
- 初涉斯坦纳树&&bzoj4774: 修路
斯坦纳树的基础应用 斯坦纳树有什么用 个人一点粗浅理解…… 最基本形式的斯坦纳树问题(以下简称母问题):给定图G和一个关键点集V.求在G中选取一个权值最小(这里权值可以有很多变式)的边集E使V中的点两 ...
- python生成四位随机数
有些时候需要发送短信给用户生成四位随机数字,这里在python中我们可以根据python自带的标准库random和string来实现. random下有三个可以随机取数的函数,分别是choice,ch ...
- 在物理机上,用U盘安装esxi虚拟化环境
一般使用U盘安装centos镜像,可使用镜像刻录工具UltraISO,详细方法参照如下链接: https://jingyan.baidu.com/article/647f0115ee55ba7f214 ...