[bzoj3123][洛谷P3302] [SDOI2013]森林(树上主席树+启发式合并)
突然发现好像没有那么难……https://blog.csdn.net/stone41123/article/details/78167288
首先有两个操作,一个查询,一个连接
查询的话,直接在树上建主席树
然后难点在于连接
用启发式合并就可以了(想了半天都没想出来)
每次合并时,我们把小的树接到大的上,然后dfs一遍小的树,更新信息
然后注意数组……别太小也别太大……(被数组大小坑了好几次提交)
//minamoto
#include<bits/stdc++.h>
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char obuf[<<],*o=obuf;
void print(int x){
if(x>) print(x/);
*o++=x%+;
}
const int N=,M=N*;
int ver[N<<],Next[N<<],head[N];
int a[N],fa[N],sz[N],b[N];
int n,m,tot,q,size,ans;
void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
}
int L[M],R[M],sum[M],rt[N],cnt;
void update(int last,int &now,int l,int r,int x){
sum[now=++cnt]=sum[last]+;
if(l==r) return;
int mid=(l+r)>>;
if(x<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x);
else L[now]=L[last],update(R[last],R[now],mid+,r,x);
}
int query(int u,int v,int lca,int lca_fa,int l,int r,int k){
if(l>=r) return l;
int x=sum[L[v]]+sum[L[u]]-sum[L[lca]]-sum[L[lca_fa]];
int mid=(l+r)>>;
if(x>=k) return query(L[u],L[v],L[lca],L[lca_fa],l,mid,k);
else return query(R[u],R[v],R[lca],R[lca_fa],mid+,r,k-x);
}
inline int hash(int x){
return lower_bound(b+,b++size,x)-b;
}
int ff(int x){
return fa[x]==x?x:fa[x]=ff(fa[x]);
}
int st[N][],d[N],vis[N];
void dfs(int u,int father,int root){
st[u][]=father;
for(int i=;i<=;++i)
st[u][i]=st[st[u][i-]][i-];
++sz[root];
d[u]=d[father]+;
fa[u]=root;
vis[u]=;
update(rt[father],rt[u],,size,hash(a[u]));
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v==father) continue;
dfs(v,u,root);
}
}
int LCA(int x,int y){
if(x==y) return x;
if(d[x]<d[y]) swap(x,y);
for(int i=;i>=;--i){
if(d[st[x][i]]>=d[y]) x=st[x][i];
}
if(x==y) return x;
for(int i=;i>=;--i){
if(st[x][i]!=st[y][i])
x=st[x][i],y=st[y][i];
}
return st[x][];
}
int main(){
//freopen("testdata.in","r",stdin);
int t=read();
n=read(),m=read(),q=read();
for(int i=;i<=n;++i)
a[i]=b[i]=read(),fa[i]=i;
sort(b+,b++n);
size=unique(b+,b++n)-b-;
for(int i=;i<=m;++i){
int u=read(),v=read();
add(u,v);
}
for(int i=;i<=n;++i)
if(!vis[i]) dfs(i,,i);
while(q--){
char ch;int x,y;
while(!isupper(ch=getc()));
x=read()^ans,y=read()^ans;
if(ch=='Q'){
int k=read()^ans;
int lca=LCA(x,y);
ans=b[query(rt[x],rt[y],rt[lca],rt[st[lca][]],,size,k)];
print(ans),*o++='\n';
}
else{
add(x,y);
int u=ff(x),v=ff(y);
if(sz[u]<sz[v]) swap(x,y),swap(u,v);
dfs(y,x,u);
}
}
fwrite(obuf,o-obuf,,stdout);
return ;
}
[bzoj3123][洛谷P3302] [SDOI2013]森林(树上主席树+启发式合并)的更多相关文章
- P3302 [SDOI2013]森林(主席树+启发式合并)
P3302 [SDOI2013]森林 主席树+启发式合并 (我以前的主席树板子是错的.......坑了我老久TAT) 第k小问题显然是主席树. 我们对每个点维护一棵包含其子树所有节点的主席树 询问(x ...
- bzoj3123 [Sdoi2013]森林 树上主席树+启发式合并
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3123 题解 如果是静态的查询操作,那么就是直接树上主席树的板子. 但是我们现在有了一个连接两棵 ...
- BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并
BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20 ...
- BZOJ2123 [Sdoi2013]森林 【主席树 + 启发式合并】
题目 输入格式 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负 ...
- bzoj 3123 [Sdoi2013]森林(主席树+启发式合并+LCA)
Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...
- [luoguP3302] [SDOI2013]森林(主席树 + 启发式合并 + lca)
传送门 显然树上第k大直接主席树 如果连边的话,我们重构小的那一棵,连到另一棵上. 说起来简单,调了我一晚上. 总的来说3个错误: 1.离散化写错位置写到了后面 2."="写成了& ...
- 洛谷 P3302 [SDOI2013]森林 解题报告
P3302 [SDOI2013]森林 题目描述 小\(Z\)有一片森林,含有\(N\)个节点,每个节点上都有一个非负整数作为权值.初始的时候,森林中有\(M\)条边. 小Z希望执行\(T\)个操作,操 ...
- p3302 [SDOI2013]森林(树上主席树+启发式合并)
对着题目yy了一天加上看了一中午题解,终于搞明白了我太弱了 连边就是合并线段树,把小的集合合并到大的上,可以保证规模至少增加一半,复杂度可以是\(O(logn)\) 合并的时候暴力dfs修改倍增数组和 ...
- 洛谷 P3302 [SDOI2013]森林 Lebal:主席树 + 启发式合并 + LCA
题目描述 小Z有一片森林,含有N个节点,每个节点上都有一个非负整数作为权值.初始的时候,森林中有M条边. 小Z希望执行T个操作,操作有两类: Q x y k查询点x到点y路径上所有的权值中,第k小的权 ...
随机推荐
- 【模板】K短路 A-star
引理:当一个状态对应的节点第K次从堆中取出时,该状态对应的当前代价是从起点到该点的第K优解. 代码如下 /* POJ2449 */ #include <cstdio> #include & ...
- word宏(macro) 之 注意事项,常见语法和学习地方
宏:计算机科学里的宏(Macro),是一种批量处理的称谓.一般说来,宏是一种规则或模式,或称语法替换 ,用于说明某一特定输入(通常是字符串)如何根据预定义的规则转换成对应的输出(通常也是字符串).这种 ...
- OpenCV教程(43) harris角的检测(1)
计算机视觉中,我们经常要匹配两幅图像.匹配的的方式就是通过比较两幅图像中的公共特征,比如边,角,以及图像块(blob)等,来对两幅图像进行匹配. 相对于边,角更适合描述图像特征, ...
- 使用ROP攻击绕过Windows的DEP
使用ROP攻击绕过Windows的DEP 基础知识 DEP DEP(Data Execution Prevention)意为数据执行保护,是Windows的一项安全机制,主要能够在内存上执行额外检查以 ...
- Python中if-else的多种写法
a, b= 1, 2 将a和b两个变量中的最大值赋值给c (1)常规写法 if a>b: c = a else: c = b (2)表达式 c = a if a>b e ...
- 远程升级云服务器系统 CentOS 6.x 至 CentOS 7.x
由于docker-ce不再支持centos6,所以觉得吧系统升级为centos7,以下是踩坑的过程 1.添加源 /etc/yum.repos.d/upgrade.repo [upgrade] name ...
- codeforces - 432D Prefixes and Suffixes (next数组)
http://codeforces.com/problemset/problem/432/D 转自:https://blog.csdn.net/tc_to_top/article/details/38 ...
- Jmeter调用 Json接口测试之关键点申明Content-Type类型
背景: 最近,在做接口测试发现创建运单接口,通过普通表单请求总是失败,开始我以为是后端接口出现问题,但通过前端页面都能创建运单,F12打开浏览器开发者模式,获取该接口请求入参发现,请求的数据格式是js ...
- 浅谈分词算法(4)基于字的分词方法(CRF)
目录 前言 目录 条件随机场(conditional random field CRF) 核心点 线性链条件随机场 简化形式 CRF分词 CRF VS HMM 代码实现 训练代码 实验结果 参考文献 ...
- 后台拿webshell方法(2)
在这里总结一下后台拿webshell的方法: 备份突破(在博客上有随笔介绍) 一般在后台上传文件类型受到限制,可以利用数据库备份将其上传的格式改为后门执行格式即可: asp更改为jpg jpg ...