题目链接

  动态开点的树链剖分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旅行(树链剖分)的更多相关文章

  1. [luogu P3384] [模板]树链剖分

    [luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...

  2. P3313 [SDOI2014]旅行——树链剖分+线段树(动态开点?)

    P3313 [SDOI2014]旅行 一棵树,其中的点分类,点有权值,在一条链上找到一类点中的最大值或总和: 树链剖分把树变成链: 把每个宗教单开一个线段树,维护区间总和和最大值: 宗教很多,需要动态 ...

  3. 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)

    题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...

  4. BZOJ 3531: [Sdoi2014]旅行 [树链剖分]

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1685  Solved: 751[Submit][Status] ...

  5. BZOJ3531:[SDOI2014]旅行(树链剖分)

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...

  6. BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树

    题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...

  7. cogs 186. [USACO Oct08] 牧场旅行 树链剖分 LCA

    186. [USACO Oct08] 牧场旅行 ★★☆   输入文件:pwalk.in   输出文件:pwalk.out   逐字节对比时间限制:1 s   内存限制:128 MB n个被自然地编号为 ...

  8. BZOJ 2157 旅行(树链剖分码农题)

    写了5KB,1发AC... 题意:给出一颗树,支持5种操作. 1.修改某条边的权值.2.将u到v的经过的边的权值取负.3.求u到v的经过的边的权值总和.4.求u到v的经过的边的权值最大值.5.求u到v ...

  9. [BZOj4336][BJOI2015]骑士的旅行(树链剖分+线段树)

    树链剖分,对每个叶子用multiset记录前K大士兵,其余节点通过从儿子归并维护前K大士兵.过于模板. #include<set> #include<cstdio> #incl ...

  10. BZOJ 3531 SDOI2014 旅行 树链剖分+线段树动态开点

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3531 题意概述: 给出一棵N个点的树,树上的每个结点有一个颜色和权值,支持以下四种操作: ...

随机推荐

  1. Logback文档(1)

    http://b6ec263c.wiz03.com/share/s/2SX2oY0nX4f32CY5ax1bapaL030VCK2svQZU2rRyDR05KMh5

  2. Android内核剖析(1)

    Linux的启动过程 开机上电执行bootloader,将内核的前n条指令加载到系统内存中------>系统内核的初始化----------->启动应用程序. bootloader的位置装 ...

  3. UVA 12171 (hdu 2771)sculptrue(离散化)

    以前对离散化的理解不够,所以把端点和区间区分来考虑但是做完这题以后有了新的认识: 先来看一个问题:给你以下的网格,你需要多少空间去存储红点区间的信息呢? 只需要图上所示的1,2,3,4个点就足够表示红 ...

  4. Codeforces Round #Pi (Div. 2) 567E President and Roads ( dfs and similar, graphs, hashing, shortest paths )

    图给得很良心,一个s到t的有向图,权值至少为1,求出最短路,如果是一定经过的边,输出"YES",如果可以通过修改权值,保证一定经过这条边,输出"CAN",并且输 ...

  5. 无旋Treap【模板】P3369

    题目 详情见链接. 代码 #include<cstdio> #include<iostream> #define outd(x) printf("%d\n" ...

  6. iperf安装与使用

    从官网下载相应版本. https://iperf.fr/iperf-download.php centos7 安装 rpm -i iperf3-3.1.3-1.fc24.x86_64.rpm ubun ...

  7. eclipse 中main()函数中的String[] args如何使用?通过String[] args验证账号密码的登录类?静态的主方法怎样才能调用非static的方法——通过生成对象?在类中制作一个方法——能够修改对象的属性值?

    eclipse 中main()函数中的String[] args如何使用? 右击你的项目,选择run as中选择 run configuration,选择arguments总的program argu ...

  8. Codevs1082 线段树练习 3

    题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下 ...

  9. C++ 学习笔记(一) cout 与printf 的不同之处

    作为一个嵌入式开发的猿,使用打印调试程序是必不可少的,拿到新的项目第一件事就是捣鼓打印.这次也不例外有打印才有耍下去的底气.在之前零零碎碎的C++学习中,还是一边学一边做项目的状态下能用printf解 ...

  10. char与varchar的区别与联系

    char是字节类型,varcahr是字符类型 1.char(20) 存放的是字节,utf-8中文字符占三个字节,GB18030兼容GBK兼容GB2312中文字符占两个字节,ISO8859-1是拉丁字符 ...