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 ...
随机推荐
- 使用Pyinstaller打包python py文件注意事项
首先需要将cmd或者PowerShell目录cd 跳转到py脚本所在目录,然后直接执行 Pyinstaller -F即可完成程序的打包,其中我们关心它有哪些常见参数: 输入参数的含义 -F 表示生成单 ...
- 自动出借-python+selenium
自动出借 import time from selenium import webdriver # import os #B username = " # 请替换成你的用户名 passwor ...
- [LeetCode] 840. Magic Squares In Grid_Easy
A 3 x 3 magic square is a 3 x 3 grid filled with distinct numbers from 1 to 9 such that each row, co ...
- response的contentType的类型值Response.ContentType
MIME类型的含义 MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开.多用于指定一些客户端自定义的文件名,以及一些媒体 ...
- 用Partimage创建或恢复分区备份
1 Preliminary Note Partimage is part of the system rescue CD found on http://www.sysresccd.org which ...
- 浅析Web API中FromBody属性
比较如下两段代码及测试结果: public class ValuesController : ApiController { // POST api/<controller> public ...
- 第五章:creat statechart diagrams for classes and use cases
- InstallShield :cannot rename directory ...
InstallShield项目编译的生成目录文件夹需要关闭.
- 笔记 : windows系统下 命令行 php --version 的版本与phpinfo()版本不一致问题
第一 : php --version命令cmd不随wamp中php版本改变而改变的, php命令是随着wamp安装时将:wamp/bin/php/php5.6.25[版本]自动或手动添加到环境变量, ...
- 219. 存在重复元素 II
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的绝对值最大为 k. 示例 1: 输入: nums = ...