【pb_ds】【平衡树启发式合并】【并查集】bzoj2733 [HNOI2012]永无乡

用并查集维护联通性。对每个联通块维护一个平衡树。合并时启发式合并。比较懒,用了pb_ds。

 1 #include<cstdio>
 2 #include<ext/pb_ds/assoc_container.hpp>
 3 #include<ext/pb_ds/tree_policy.hpp>
 4 using namespace std;
 5 using namespace __gnu_cxx;
 6 using namespace __gnu_pbds;
 7 tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> T[100001];
 8 tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>::iterator it;
 9 int num[100001],val[100001],fa[100001],rank[100001];
10 int n,m,q,x,y,f1,f2;
11 char op[2];
12 int Res,Num;char C,CH[20];
13 inline int G()
14 {
15     Res=0;C=‘*‘;
16     while(C<‘0‘||C>‘9‘)C=getchar();
17     while(C>=‘0‘&&C<=‘9‘){Res=Res*10+(C-‘0‘);C=getchar();}
18     return Res;
19 }
20 inline void P(int x)
21 {
22     Num=0;while(x>0)CH[++Num]=x%10,x/=10;
23     while(Num)putchar(CH[Num--]+48);
24     putchar(‘\n‘);
25 }
26 void init()
27 {
28     for(int i=1;i<=n;i++)
29       fa[i]=i;
30 }
31 int findroot(int x)
32 {
33     if(fa[x]==x)
34       return x;
35     int rt=findroot(fa[x]);
36     fa[x]=rt;
37     return rt;
38 }
39 void Union(const int &u,const int &v)
40 {
41     if(rank[u]<rank[v])
42       {
43           fa[u]=v;
44           for(it=T[u].begin();it!=T[u].end();it++)
45             T[v].insert((*it));
46           T[u].clear();
47       }
48     else
49       {
50         fa[v]=u;
51         for(it=T[v].begin();it!=T[v].end();it++)
52             T[u].insert((*it));
53           T[v].clear();
54         if(rank[u]==rank[v]) rank[u]++;
55       }
56 }
57 int main()
58 {
59     n=G();m=G();
60     init();
61     for(int i=1;i<=n;i++)
62       {
63           val[i]=G();
64           T[i].insert(val[i]);
65           num[val[i]]=i;
66       }
67     for(int i=1;i<=m;i++)
68       {
69           x=G();y=G();
70           f1=findroot(x),f2=findroot(y);
71           if(f1!=f2) Union(f1,f2);
72       }
73     q=G();
74     for(int i=1;i<=q;i++)
75       {
76           scanf("%s",op);x=G();y=G();
77           if(op[0]==‘Q‘)
78             {
79                 f1=findroot(x);
80                 if(T[f1].size()<y) puts("-1");
81                 else P(num[*T[f1].find_by_order(y-1)]);
82             }
83           else
84             {
85                 f1=findroot(x),f2=findroot(y);
86               if(f1!=f2) Union(f1,f2);
87             }
88       }
89     return 0;
90 }
时间: 2024-10-11 12:45:55

【pb_ds】【平衡树启发式合并】【并查集】bzoj2733 [HNOI2012]永无乡的相关文章

bzoj2733: [HNOI2012]永无乡(splay)

2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3778  Solved: 2020 Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的.现在有两

[BZOJ2733] [HNOI2012]永无乡(并查集 + 线段树合并)

传送门 一看到第k大就肯定要想到什么权值线段树,主席树,平衡树之类的 然后就简单了 用并查集判断连通,每个节点建立一颗权值线段树,连通的时候直接合并即可 查询时再二分递归地查找 时间复杂度好像不是很稳定...但hzwer都用这种方法水过.. 正解好像是平衡树+启发式合并,以后学TT #include <cstdio> #include <iostream> #define N 100001 int n, m, q, cnt; int a[N], f[N], sum[N * 20],

[BZOJ2733] [HNOI2012] 永无乡 (splay启发式合并)

Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的.现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥.Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k

bzoj2733: [HNOI2012]永无乡(splay+启发式合并/线段树合并)

这题之前写过线段树合并,今天复习Splay的时候想起这题,打算写一次Splay+启发式合并. 好爽!!! 写了长长的代码(其实也不长),只凭着下午的一点记忆(没背板子...),调了好久好久,过了样例,submit,1A! 哇真的舒服 调试输出懒得删了QwQ #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<queue> #include

[bzoj2733] [HNOI2012]永无乡

写了线段树合并..具体合并姿势和可并堆基本一样.. 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=100233,mxnode=maxn*20; 7 int lc[mxnode],rc[mxnode],sz[mxnode],tot; 8 int rt[maxn],f

BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)

不难...treap + 启发式合并 + 并查集 搞搞就行了 ---------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define rep(i, n) for(int i = 0; i &l

Bzoj 2733: [HNOI2012]永无乡 数组Splay+启发式合并

2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3955  Solved: 2112[Submit][Status][Discuss] Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含 0 座)桥可以到达

【bzoj2733】[HNOI2012]永无乡 线段树合并

Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的.现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥.Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k

BZOJ 2733 [HNOI2012]永无乡(启发式合并+Treap+并查集)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2733 [题目大意] 给出n个点,每个点都有自己的重要度,现在有连边操作和查询操作, 查询操作要求找出一个连通块中重要度第k的点的id [题解] 我们用Treap维护每个连通块,对于连边操作,我们用启发式合并, 将size比较小的Treap并入size比较大的Treap,同时用并查集维护连通信息 [代码] #include <cstdio> #include <algorith