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 ...
随机推荐
- 乐固加固后windows下实现给apk签名
遇到了这样一个问题:我们已经在centos下签名生成好的apk,拿到腾讯乐固上加固以后,签名没有了,就需要重新签名,我乐滋滋的想,既然原来是在centos下签名的,那再去centos上签名一次就好了, ...
- HttpwebRequest - 带ViewState的网页POST请求
这是我今天下午碰到的案例,一个退订页面的post请求,请求头信息都很明确,but看看下面这个请求体,除了最后一个key是我的页面控件名称,其他的几个ViewState相关都是what呢?(ViewSt ...
- centos 6.x下编译dpdk 16.7 心得
之前对dpdk编译了解得较少,之前直接就把centos yum update了,造成测试经理部署的centos 6.5升级为6.9,造成dpdk编译出错. 先说说centos 6.9下编译的心得: 1 ...
- 输出调试技巧 PRINTF()
#define PRINTF(...) \ do { \ printf( "%d:%s::",__LINE__, __FUNCTION__);\ printf(__VA_ARGS_ ...
- Bootstrap-按钮相关的class
.btn 基础class.btn-default 白底黑字的按钮.btn-warning 红色按钮.btn-success 绿色按钮.btn-info 浅蓝色按钮.bt ...
- 并查集(disjoint)
合并,查找的集合 第一,建立两个函数,一个用来查找(find),一个用来合并(merge): 如下的一个模板: 题目: 亲戚(Relations) 或许你并不知道,你的某个朋友是你的亲戚.他可能是你的 ...
- DX9 DirectX键盘控制程序 代码
// @time: 2012.3.26 // @author: jadeshu // des: DirectX键盘控制程序 #include <Windows.h> #include &l ...
- rpgmakermv(10) GraphicalDesignMode
插件地址:https://github.com/triacontane/RPGMakerMV/blob/master/GraphicalDesignMode.js 原文: メニュー画面や戦闘画面など各 ...
- DataSet 读取xml 报错有非法字符
private void Bind() { string strLogPath = ConfigurationSettings.AppSettings["LOG_PATH"].To ...
- CSS选择符-----关系选择符
包含选择符(E F) 选择所有被E元素包含的F元素 与 子选择符(E>F) 不同的是,包含选择符将会命中所有符合条件的后代,包括儿子,孙子,孙子的孙子... <! ...