bzoj 2733 平衡树启发式合并
首先对于一个连通块中,询问我们可以直接用平衡树来求出排名,那么我们可以用并查集来维护各个块中的连通情况,对于合并两个平衡树,我们可以暴力的将size小的平衡树中的所有节点删掉,然后加入大的平衡树中,因为每个点只可能被删除插入logn次,所以时间复杂度为nlog^2n。
/**************************************************************
Problem: 2733
User: BLADEVIL
Language: C++
Result: Accepted
Time:2112 ms
Memory:64868 kb
****************************************************************/
//By BLADEVIL
#include <cstdio>
#define maxn 100010
#define maxt 4000010
using namespace std;
int n,m;
int father[maxn],a[maxn],root[maxn];
int left[maxt],right[maxt],size[maxt],key[maxt];
int tot,save;
int adr[maxn];
int getfather(int x)
{
if (father[x]==x) return x;
return father[x]=getfather(father[x]);
}
void swap(int &x,int &y)
{
int z=x;
x=y; y=z;
}
void left_rotate(int &t)
{
int k=right[t];
right[t]=left[k];
left[k]=t;
size[k]=size[t];
size[t]=size[left[t]]+size[right[t]]+;
t=k;
}
void right_rotate(int &t)
{
int k=left[t];
left[t]=right[k];
right[k]=t;
size[k]=size[t];
size[t]=size[left[t]]+size[right[t]]+;
t=k;
}
void maintain(int &t,bool flag)
{
if (!flag)
{
if (size[left[left[t]]]>size[right[t]])
right_rotate(t); else
if (size[right[left[t]]]>size[right[t]])
left_rotate(left[t]),right_rotate(t); else return;
} else
{
if (size[right[right[t]]]>size[left[t]])
left_rotate(t); else
if (size[left[right[t]]]>size[left[t]])
right_rotate(right[t]),left_rotate(t); else return;
}
maintain(left[t],); maintain(right[t],);
maintain(t,); maintain(t,);
}
void t_insert(int &t,int v)
{
if (!t)
{
t=++tot;
left[t]=right[t]=;
key[t]=v;
size[t]=;
} else
{
size[t]++;
if (v>key[t]) t_insert(right[t],v); else t_insert(left[t],v);
maintain(t,v>key[t]);
}
}
int t_delete(int &t,int v)
{
size[t]--;
if ((key[t]==v)||((v>key[t])&&(!right[t]))||((v<key[t])&&(!left[t])))
{
save=key[t];
if ((!left[t])||(!right[t]))
t=left[t]+right[t]; else key[t]=t_delete(left[t],v+);
} else
return (v>key[t])?t_delete(right[t],v):t_delete(left[t],v);
}
int t_rank(int &t,int k)
{
if (size[left[t]]+==k) return key[t];
return (k<=size[left[t]])?t_rank(left[t],k):t_rank(right[t],k-size[left[t]]-);
}
void combine(int x,int y)
{
int fx,fy;
fx=getfather(x); fy=getfather(y);
if (size[root[fx]]<size[root[fy]]) swap(fx,fy);
father[fy]=fx;
if (fx!=fy)
{
fy=root[fy];
while (root[fy])
{
t_insert(root[fx],a[fy]);
t_delete(root[fy],a[fy]);
}
}
}
void ask(int x,int k)
{
x=root[getfather(x)];
if (size[x]>=k) printf("%d\n",adr[t_rank(x,k)]); else printf("-1\n");
}
void init()
{
int x,y;
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) scanf("%d",&a[i]);
for (int i=;i<=n;i++) adr[a[i]]=i;
for (int i=;i<=n;i++) father[i]=i,t_insert(root[i],a[i]);
while (m--)
{
scanf("%d%d",&x,&y);
combine(x,y);
}
}
void solve()
{
int test,x,y;
char s[];
scanf("%d",&test);
while (test--)
{
scanf("%s%d%d",&s,&x,&y);
if (s[]=='B')
combine(x,y); else ask(x,y);
}
}
int main()
{
init();
solve();
return ;
}
bzoj 2733 平衡树启发式合并的更多相关文章
- bzoj 2733 Splay 启发式合并,名次树
题意:给定一个带点权的无向图,有两种操作: 1.将两个连通分量合并. 2.查询某个连通分量里的第K大点. 题解: 用并查集维护连通关系,一开始建立n棵splay树,然后不断合并,查询. 处理技巧: 1 ...
- BZOJ 2809: [Apio2012]dispatching( 平衡树 + 启发式合并 )
枚举树上的每个结点做管理者, 贪心地取其子树中薪水较低的, 算出这个结点为管理者的满意度, 更新答案. 用平衡树+启发式合并, 时间复杂度为O(N log²N) ------------------- ...
- ☆ [HNOI2012] 永无乡 「平衡树启发式合并」
题目类型:平衡树启发式合并 传送门:>Here< 题意:节点可以连边(不能断边),询问任意两个节点的连通性与一个连通块中排名第\(k\)的节点 解题思路 如果不需要询问排名,那么并查集即可 ...
- bzoj 2809 左偏树\平衡树启发式合并
首先我们对于一颗树,要选取最多的节点使得代价和不超过m,那么我们可以对于每一个节点维护一个平衡树,平衡树维护代价以及代价的和,那么我们可以在logn的时间内求出这个子树最多选取的节点数,然后对于一个节 ...
- BZOJ 2733 & splay的合并
题意: 带权联通块,添边与查询联通块中第k大. SOL: splay合并+并查集. 我以为splay可以用奇技淫巧来简单合并...调了一下午终于幡然醒悟...于是就只好一个一个慢慢插...什么启发式合 ...
- 【pb_ds】【平衡树启发式合并】【并查集】bzoj2733 [HNOI2012]永无乡
用并查集维护联通性.对每个联通块维护一个平衡树.合并时启发式合并.比较懒,用了pb_ds. #include<cstdio> #include<ext/pb_ds/assoc_con ...
- 【BZOJ1483】[HNOI2009]梦幻布丁(平衡树启发式合并+并查集)
题目: BZOJ1483 分析: (这题码了一下午,码了近250行,但是意外跑的比本校各位神仙稍快,特写博客纪念) 首先能看出一个显然的结论:颜色段数只会变少不会变多. 我们考虑用并查集维护区间,对于 ...
- bzoj 1483 链表 + 启发式合并
思路:将颜色相同的建成一个链表, 变颜色的时候进行链表的启发式合并.. 因为需要将小的接到大的上边,所以要用个f数组. #include<bits/stdc++.h> #define LL ...
- bzoj 1483 链表启发式合并
首先我们可以比较容易的在n的时间内算出来开始的答案,我们维护一些链表,分别表示不同的颜色,那么我们在计算答案的时候,只需要扫一遍所有的链表,判断链表相邻两项是否在序列中相邻,不相邻的话肯定在这其中的一 ...
随机推荐
- 在linux下如何显示隐藏文件
#显示所有文件(包含隐藏文件)ls -a #只显示隐藏文件l.或者ls -d .* #在XWindow的KDE桌面中在"查看(View)"菜单里选"显示隐藏文件(Show ...
- 【Spring.Net】- 环境搭建
参考文章:http://www.cnblogs.com/GoodHelper/archive/2009/10/25/SpringNET_Config.html 一.环境下载及安装 到Spring的官方 ...
- mysql突然无法启动的问题
经常会有这样一个情况是:mysql跑了一段时间后,某一天我们需要重启服务的时候,发现停止后并不能正常启动,会报下面这种错误 这种情况发生的原因绝大多数都是权限的问题: 因为使用了一段时间后,使用期间表 ...
- Struts2自定义结果视图(servlet验证码)
1.编写一个类实现com.opensymphony.xwork2.Result,或者继承org.apache.struts2.dispatcher.StrutsResultSupport 2.自定义的 ...
- JavaScript中:表达式和语句的区别
JavaScript中:表达式和语句的区别 Javascript语言精粹:表达式是由运算符构成,并运算产生结果的语法结构.程序是由语句构成,语句则是由“:(分号)”分隔的句子或命令.如果在表达式后面加 ...
- CentOS 输入输出重定向
标准输入重定向(STDIN,文件描述符为 0):默认从键盘输入,也可从其他文件或命令中输入.(文件描述符可以省略) 标准输出重定向(STDOUT,文件描述符为 1):默认输出到屏幕.(文件描述符可以省 ...
- 【刷题】BZOJ 3527 [Zjoi2014]力
Description 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. Input 第一行一个整数n. 接下来n行每行输入一个数,第i行表示qi. n≤100000,0<qi ...
- [LOJ #2473] [九省联考2018] 秘密袭击coat
题目链接 洛谷. LOJ,LOJ机子是真的快 Solution 我直接上暴力了...\(O(n^2k)\)洛谷要\(O2\)才能过...loj平均单点一秒... 直接枚举每个点为第\(k\)大的点,然 ...
- Android ListView的优化
最近的项目中有通讯录这个模块,里面的通讯录涉及的联系人数量很大,导致在加载页面的时候有点卡,所以就必须得进行优化,优化的最终实现理论是什么?就是让ListView一次性加载的数据较少,后续根据用户操作 ...
- POJ2074:Line of Sight——题解
http://poj.org/problem?id=2074 题目大意:(下面的线段都与x轴平行)给两条线段,一个点在其中一条线段看另一条线段,但是中间有很多线段阻挡视线.求在线段上最大连续区间使得在 ...