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. centos上shellcheck的安装

    关于shellcheck的作用和功能,自行查阅. centos7 上安装shellcheck的过程中查了很多资料,大部分都是在ubunt下安装的,centos的比较少,然后好不容易看到一个https: ...

  2. python mysql program

    //test.py #!/usr/bin/python # -*- coding: UTF-8 -*- import MySQLdb # 打开数据库连接 db = MySQLdb.connect(&q ...

  3. cocos2d-x JS 弹出对话框触摸监听(吞噬点击事件遮挡层)

    在游戏中,我们经常会碰到一些弹窗,这些弹窗禁止点透,也就是禁止触摸事件传递到底层,我们称之为遮挡层,这些遮挡层,需要开发遮挡层,我们首先得了解cocos2d-js的触摸传递机制. 根据官方文档,我们可 ...

  4. HDU 3117 Fibonacci Numbers(矩阵)

    Fibonacci Numbers [题目链接]Fibonacci Numbers [题目类型]矩阵 &题解: 后4位是矩阵快速幂求,前4位是用log加Fibonacci通项公式求,详见上一篇 ...

  5. mongodb对数组元素及内嵌文档进行增删改查操作(转)

    from:https://my.oschina.net/132722/blog/168274 比如我有一个user类,他包含一个标签属性,这个标签是一个数组,数组里面的元素是内嵌文档,格式如下: &l ...

  6. Java包装

    public class Test2 { public static void main(String[] args) { /*String str = "..............&qu ...

  7. 解决ORA-00257: 归档程序错误。在释放之前仅限于内部连接

    昨天尝试通过plsqldev尝试连接oracle数据库,报错,提示ORA-00257: 归档程序错误.在释放之前仅限于内部连接 通过查询,得知原因是archivedlog达到了数据库设置的空间限制. ...

  8. python中安装并使用redis

    数据缓存系统:1:mongodb:是直接持久化,直接存储于硬盘的缓存系统2:redis: 半持久化,存储于内存和硬盘3:memcache:数据只能存储在内存里的缓存系统 redis是一个key-val ...

  9. Rpgmakermv(38)MOG_Theatrhythm

    1.============================葡萄牙语=================================================+++ MOG - Theatrh ...

  10. Mysql常规优化

    一.SQL语句优化 (1)使用limit对查询结果的记录进行限定(2)避免select *,将需要查找的字段列出来(3)使用连接(join)来代替子查询(4)拆分大的delete或insert语句 二 ...