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]森林(主席树+启发式合并)的更多相关文章

  1. Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)

    3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当前 ...

  2. [bzoj3123] [SDOI2013]森林 主席树+启发式合并+LCT

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  3. BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]

    3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...

  4. luoguP3302 [SDOI2013]森林 主席树 启发式合并

    题目链接 luoguP3302 [SDOI2013]森林 题解 本来这题树上主席树暴力启发式合并就完了 结果把lca写错了... 以后再也不这么写了 复杂度\(O(nlog^2n)\) "f ...

  5. [BZOJ3123][Sdoi2013]森林 主席树+启发式合并

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当 ...

  6. [SDOI2013]森林 主席树+启发式合并

    这题的想法真的很妙啊. 看到题的第一眼,我先想到树链剖分,并把\(DFS\)序当成一段区间上主席树.但是会发现在询问的时候,可能会非常复杂,因为你需要把路径拆成很多条轻链和重链,它们还不一定连续,很难 ...

  7. 【BZOJ 3123】 [Sdoi2013]森林 主席树启发式合并

    我们直接按父子关系建主席树,然后记录倍增方便以后求LCA,同时用并查集维护根节点,而且还要记录根节点对应的size,用来对其启发式合并,然后每当我们合并的时候我们都要暴力拆小的一部分重复以上部分,总时 ...

  8. 【BZOJ-3123】森林 主席树 + 启发式合并

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2738  Solved: 806[Submit][Status] ...

  9. BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并

    BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20 ...

随机推荐

  1. Spring MVC定时服务

    spring-mvc-config.xml <context:component-scan base-package="com.bf" ></context:co ...

  2. c#中取整和取余

    "%"为取余. "/"号整型运算是取整,浮点运算时为除法运算.如54/10结果为5,54.0/10.0结果为5.4.而且取整时不进行四舍五入只取整数部分,如54 ...

  3. Nginx参数调优

    (1)nginx运行工作进程个数,一般设置cpu的核心或者核心数x2 如果不了解cpu的核数,可以top命令之后按1看出来,也可以查看/proc/cpuinfo文件 grep ^processor / ...

  4. Golang package

    今天,灵感一现:不能一个文件干到底吧,那要是工程大了怎么办? 答案很简单,“包”啊 GO里的包,看起来很简单,但又不简单 一开始,我想当然的以为就是include 路径一样的问题 事实是,GO以GOP ...

  5. WebAssembly 浏览器中运行c/c++模块

    今天,要给前端造点儿福利 浏览器中能调用javascript,曾经我们以为够用了,够强大了,但是事实上是完全不够 还好,mozilla的工程师提出了webassembly,目前是利用emsctript ...

  6. Git安装及创建版本库

    一.在Windows上安装Git 1.虽然用于开发的系统最好是用Mac或者Linux,但绝大多数新人都是用Windows进行开发.Windows系统上也有提供了Git(Windows版),下载地址:h ...

  7. HTML5 缓存

    一.在html/htm文件中声明缓存,声明方式: <!DOCTYPE HTML> <html manifest="demo.appcache">...3 & ...

  8. jdbc连接oracle时使用的字符串格式

    两种方式: SID的方式: jdbc:oracle:thin:@[HOST][:PORT]:SID SERVICE_NAME的方式: jdbc:oracle:thin:@//[HOST][:PORT] ...

  9. 在TensorFlow中运行程序多次报错:AttributeError: __exit__

    我没有记住语句 with tf.Session() as sess: 多次写成了 with tf.Session as sess: 吃括号这个低级的错误又犯了,真不应该,立下flag:以后再犯相同的错 ...

  10. PM2管理工具的使用

    linux上PM2可以管理服务程序,防止程序无故关闭,具有程序守护功能,自动重启服务器程序,监控程序等好处,很方便,具体自己去体会! 官网地址:  http://pm2.keymetrics.io/ ...