P3302 [SDOI2013]森林(主席树+启发式合并)
主席树+启发式合并
(我以前的主席树板子是错的.......坑了我老久TAT)
第k小问题显然是主席树。
我们对每个点维护一棵包含其子树所有节点的主席树
询问(x,y)的时候用倍增找到(x,y)的lca,蓝后树上差分一下,即:
$total_{size}=sum[x]+sum[y]-sum[lca]-sum[fa[lca]]$
至于合并两棵树........我们把小的那棵树接到大的那棵上,并把小树上的主席树都重构一遍
这就是启发式合并,合并的复杂度大概为$O(nlogn)$
数据......离散化一下就好辣
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline void Swap(int &a,int &b){a^=b^=a^=b;}
void read(int &x){
static char c=getchar();x=; int f=;
while(c<''||c>'') f=f&&(c!='-'),c=getchar();
while(''<=c&&c<='') x=x*+(c^),c=getchar();
x=f?x:-x;
}
#define N 80005
#define W 20000005
int TAT,n,m,T,tn,a[N],b[N],w[N],Rt[N],Siz[N],Pre;
int u,rt[N],lc[W],rc[W],siz[W];
int fa[N],Fa[][N],d[N];
int cnt,hd[N],nxt[N<<],ed[N],poi[N<<];
bool vis[N];
inline void adde(int x,int y){
nxt[ed[x]]=++cnt, hd[x]=hd[x]?hd[x]:cnt,
ed[x]=cnt, poi[cnt]=y;
}
inline int Id(int x){return lower_bound(b+,b+tn+,x)-b;}
#define mid (l+r)/2
void Ins(int &o,int p,int l,int r,int x){
if(!o) o=++u;
siz[o]=siz[p]+;
if(l==r) return ;
if(x<=mid) rc[o]=rc[p],Ins(lc[o],lc[p],l,mid,x);
else lc[o]=lc[p],Ins(rc[o],rc[p],mid+,r,x);
}
int Ask(int x,int y,int c1,int c2,int l,int r,int k){
if(l==r) return b[l];
int tmp=siz[lc[x]]+siz[lc[y]]-siz[lc[c1]]-siz[lc[c2]];
if(k<=tmp) return Ask(lc[x],lc[y],lc[c1],lc[c2],l,mid,k);
else return Ask(rc[x],rc[y],rc[c1],rc[c2],mid+,r,k-tmp);
}
void dfs(int x,int RT){
Fa[][x]=fa[x]; d[x]=d[fa[x]]+; vis[x]=;
for(int i=;i<=;++i) Fa[i][x]=Fa[i-][Fa[i-][x]];//不能写成(1<<i)<=d[x],因为我们并没有把之前的废弃点完全删除,必须全部覆盖掉
++Siz[RT]; Rt[x]=RT;
Ins(rt[x],rt[fa[x]],,tn,Id(a[x]));
for(int i=hd[x];i;i=nxt[i])
if(poi[i]!=fa[x])
fa[poi[i]]=x,dfs(poi[i],RT);
}
int LCA(int x,int y){
if(d[x]<d[y]) Swap(x,y);
for(int i=;i>=;--i) if(d[Fa[i][x]]>=d[y]) x=Fa[i][x];
if(x==y) return x;
for(int i=;i>=;--i) if(Fa[i][x]!=Fa[i][y]) x=Fa[i][x],y=Fa[i][y];
return Fa[][x];
}
int main(){
register int i; char opt[]; int q1,q2,q3,lca;
read(TAT);read(n);read(m);read(T);
for(i=;i<=n;++i) read(a[i]),w[i]=a[i];
while(m--) read(q1),read(q2),adde(q1,q2),adde(q2,q1);
sort(w+,w+n+); b[tn=]=w[];
for(i=;i<=n;++i) if(w[i]!=w[i-]) b[++tn]=w[i]; //离散化
for(i=;i<=n;++i) if(!vis[i]) dfs(i,i);
while(T--){
scanf("%s",opt);read(q1);read(q2);q1^=Pre;q2^=Pre;
if(opt[]=='L'){
adde(q1,q2),adde(q2,q1);
if(Siz[Rt[q1]]<Siz[Rt[q2]]) Swap(q1,q2);
fa[q2]=q1; dfs(q2,Rt[q1]);//启发式合并,小树连到大树上
}else{
read(q3); q3^=Pre; lca=LCA(q1,q2);
Pre=Ask(rt[q1],rt[q2],rt[lca],rt[fa[lca]],,tn,q3);
printf("%d\n",Pre);
}
}return ;
}
P3302 [SDOI2013]森林(主席树+启发式合并)的更多相关文章
- Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当前 ...
- [bzoj3123] [SDOI2013]森林 主席树+启发式合并+LCT
Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...
- BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]
3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...
- luoguP3302 [SDOI2013]森林 主席树 启发式合并
题目链接 luoguP3302 [SDOI2013]森林 题解 本来这题树上主席树暴力启发式合并就完了 结果把lca写错了... 以后再也不这么写了 复杂度\(O(nlog^2n)\) "f ...
- [BZOJ3123][Sdoi2013]森林 主席树+启发式合并
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当 ...
- [SDOI2013]森林 主席树+启发式合并
这题的想法真的很妙啊. 看到题的第一眼,我先想到树链剖分,并把\(DFS\)序当成一段区间上主席树.但是会发现在询问的时候,可能会非常复杂,因为你需要把路径拆成很多条轻链和重链,它们还不一定连续,很难 ...
- 【BZOJ 3123】 [Sdoi2013]森林 主席树启发式合并
我们直接按父子关系建主席树,然后记录倍增方便以后求LCA,同时用并查集维护根节点,而且还要记录根节点对应的size,用来对其启发式合并,然后每当我们合并的时候我们都要暴力拆小的一部分重复以上部分,总时 ...
- 【BZOJ-3123】森林 主席树 + 启发式合并
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2738 Solved: 806[Submit][Status] ...
- BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并
BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20 ...
随机推荐
- 通过官方API结合源码,如何分析程序流程
通过官方API结合源码,如何分析程序流程通过官方API找到我们关注的API的某个方法,然后把整个流程执行起来,然后在idea中,把我们关注的方法打上断点,然后通过Step Out,从内向外一层一层分析 ...
- U盘复制文件到最后5秒会卡住怎么办解决
现在的U盘容量已经非常大了,一般都有16G以上,为了能放单文件大于4G的数据大多数时候我们都是把U盘格式化为ntfs格式的,所以会出现不管是大文件还是小文件,当你往U盘里复制文件或者使用发送到U盘功能 ...
- 20165321实验一Java开发环境的熟悉-1
- case insensitive in php
date: 2017-07-27 PHP的命名空间是否区分大小写? 结论:不区分大小写,与类名一样(不区分大小写). 不区分大小写的包括 函数名 方法名 类名 控制语句(if, else, for, ...
- 再次 WebAssembly 技术探讨
上次说到你可以将C代码编译成web调用的js文件,当时,很兴奋.哈哈,我也误以为是系统级别的C编程呢! 哎,今天,告诉你一个残酷的事实是,只是C语言级别,不是系统级别.因为WebAssembly目标是 ...
- 记录一则完整的SPA(10g->11g)测试过程
生产端:Windows 2008 + Oracle 10.2.0.5 测试端:RHEL 6.5 + Oracle 11.2.0.4 需求:因为Oracle跨越大版本,优化器.新特性变动较多,需要进行S ...
- sqlmap常用技巧整理
言 通过在乌云网上出现的很多SQL注入漏洞,因此来总结一下,大致使用SQLMAP所遇到的参数. 基本结构 基本SQLMAP的使用方式就如下所示,使用参数式的方式,按需求添加. 12 sqlmap.py ...
- vue框架(三)_vue引入jquery、bootstrap
一.vue安装jquery 1.按照之前博客的内容,新建一个vue工程. 2.在项目文件夹下,使用命令npm install jquery --save-dev 引入jquery. 3.在build/ ...
- Oil Deposits HDU 1241
The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSu ...
- hdu5439 二分
题意 初始给了 1 2 两个数 第二步 因为第2个数是2 所以 在序列后面放上2个2 包括他自己之前有的 序列变成 1 2 2 第三步 因为第3个数是2 所以 在序列后面放上2个3 就变成了 1 ...