博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 2733 平衡树启发式合并
阅读量:6495 次
发布时间:2019-06-24

本文共 2900 字,大约阅读时间需要 9 分钟。

  首先对于一个连通块中,询问我们可以直接用平衡树来求出排名,那么我们可以用并查集来维护各个块中的连通情况,对于合并两个平衡树,我们可以暴力的将size小的平衡树中的所有节点删掉,然后加入大的平衡树中,因为每个点只可能被删除插入logn次,所以时间复杂度为nlog^2n。

  

/**************************************************************    Problem: 2733    User: BLADEVIL    Language: C++    Result: Accepted    Time:2112 ms    Memory:64868 kb****************************************************************/ //By BLADEVIL#include 
#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]]+1;    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]]+1;    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],0); maintain(right[t],1);    maintain(t,1); maintain(t,0);} void t_insert(int &t,int v){    if (!t)    {        t=++tot;        left[t]=right[t]=0;        key[t]=v;        size[t]=1;    } 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])?t_delete(right[t],v):t_delete(left[t],v);} int t_rank(int &t,int k){    if (size[left[t]]+1==k) return key[t];    return (k<=size[left[t]])?t_rank(left[t],k):t_rank(right[t],k-size[left[t]]-1);} void combine(int x,int y){    int fx,fy;    fx=getfather(x); fy=getfather(y);    if (size[root[fx]]
=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=1;i<=n;i++) scanf("%d",&a[i]);    for (int i=1;i<=n;i++) adr[a[i]]=i;    for (int i=1;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[10];    scanf("%d",&test);    while (test--)    {        scanf("%s%d%d",&s,&x,&y);        if (s[0]=='B')            combine(x,y); else ask(x,y);    }} int main(){    init();    solve();    return 0;}

 

转载于:https://www.cnblogs.com/BLADEVIL/p/3625681.html

你可能感兴趣的文章
2015 Multi-University Training Contest 2 1002 Buildings
查看>>
java 产生的固体物的基础上 增删改的SQL声明
查看>>
在自己的网站添加关注新浪关注按钮
查看>>
【MySQL笔记】mysql来源安装/配置步骤和支持中国gbk/gb2312编码配置
查看>>
一句话的设计模式(转)
查看>>
(剑指Offer)面试题54:表示数值的字符串
查看>>
Centos下安装mysql 总结
查看>>
ORM武器:NHibernate(三)五个步骤+简单对象CRUD+HQL
查看>>
UIScrollView offset in UINavigationController
查看>>
怎么从sqlserver 数据库导出 insert 的数据语句
查看>>
BZOJ4245 : [ONTAK2015]OR-XOR
查看>>
Android Properties 存储
查看>>
setenv 和 set
查看>>
.sh
查看>>
碱基序列的儿子最长上涨
查看>>
Android UI SurfaceView的使用-绘制组合图型,并使其移动
查看>>
C# 属性、索引
查看>>
(转)Java多线程之Lock的使用 (待整理)
查看>>
Java中Filter、Servlet、Listener的学习
查看>>
Java Code Examples for javax.servlet.http.Part
查看>>