传送门

Luogu

解题思路

很容易想到平衡树,然后还可以顺便维护一下连通性,但是如何合并两棵平衡树?

我们采用一种类似于启发式合并的思想,将根节点siz较小的那颗平衡树暴力的合并到另一颗上去。

那么复杂度呢?

由于一个点所在的平衡树在经过这样一次合并之后,根节点的siz至少乘2,所以每一次合并的复杂度是 \(O(n\log n)\) 的,所以整个算法的复杂度也就维持在了 \(O(n\log n)\) 级别,这题就搞定了。

细节注意事项

  • 咕咕咕

参考代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while (!isdigit(c)) f |= (c == '-'), c = getchar();
while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
s = f ? -s : s;
}
const int _ = 100010;
int n, m, q, rt[_];
inline int findd(int x) { return rt[x] == x ? x : rt[x] = findd(rt[x]); }
int tot, val[_], pri[_], ls[_], rs[_], siz[_];
inline int newnode(int v)
{ return siz[++tot] = 1, pri[tot] = rand(), val[tot] = v, tot; }
inline void pushup(int p) { siz[p] = siz[ls[p]] + siz[rs[p]] + 1; }
inline void split(int p, int v, int& x, int& y) {
if (!p) return (void) (x = y = 0);
if (val[p] <= v)
x = p, split(rs[p], v, rs[p], y);
else
y = p, split(ls[p], v, x, ls[p]);
pushup(p);
}
inline int merge(int x, int y) {
if (!x || !y) return x + y;
if (pri[x] < pri[y])
return rs[x] = merge(rs[x], y), pushup(x), x;
else
return ls[y] = merge(x, ls[y]), pushup(y), y;
}
inline int kth(int p, int k) {
if (siz[ls[p]] + 1 > k) return kth(ls[p], k);
if (siz[ls[p]] + 1 == k) return p;
if (siz[ls[p]] + 1 < k) return kth(rs[p], k - siz[ls[p]] - 1);
}
inline void dfs(int x, int& y) {
if (!x) return;
dfs(ls[x], y);
dfs(rs[x], y);
int a, b;
split(y, val[x], a, b);
y = merge(merge(a, x), b);
}
inline int unionn(int x, int y) {
if (siz[x] > siz[y]) swap(x, y);
return dfs(x, y), y;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
#endif
srand(time(0)), read(n), read(m);
for (rg int v, i = 1; i <= n; ++i)
read(v), rt[i] = newnode(v);
for (rg int x, y, i = 1; i <= m; ++i) {
read(x), x = findd(x);
read(y), y = findd(y);
if (x == y) continue;
rt[x] = rt[y] = unionn(rt[x], rt[y]);
}
read(q);
char s[5];
for (rg int x, y, i = 1; i <= q; ++i) {
scanf("%s", s), read(x), read(y);
if (s[0] == 'Q') {
x = findd(x);
if (siz[x] < y) puts("-1");
else printf("%d\n", kth(x, y));
} else {
x = findd(x), y = findd(y);
if (x == y) continue;
rt[x] = rt[y] = unionn(rt[x], rt[y]);
}
}
return 0;
}

完结撒花 \(qwq\)

最新文章

  1. Nginx的启动脚本(Centos)
  2. 【腾讯GAD暑期训练营游戏程序班】游戏中的特效系统作业说明文档
  3. [Unity3D]NGUI用Sprite动画和屏幕自适应做游戏开始场景
  4. iOS Xcode编译报错问题解决办法汇总
  5. win7下安装redies
  6. 去除VA(Visual Assist)中文注释的红色波浪线
  7. SMW0上传EXCEL模板时报错无分配给对象***的MIME类型
  8. asp.net,CSS设置&lt;TableListView&gt;的title居左,居左,居上
  9. mysql ERROR1405 access deny 问题解决
  10. 【转】【iOS知识学习】_视图控制对象生命周期-init、viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear等的区别及用途
  11. LOL游戏程序中对一些函数的Hook记录(Win10 x64)
  12. Android利用Fiddler进行网络数据抓包,手机抓包工具汇总
  13. push类型消息中间件-消息服务端(三)
  14. 关于团购VPS的事情报告
  15. [JZOJ3615]【NOI2014模拟】数列(平面几何+二维线段树)
  16. Tree Traversals Again
  17. noip第27课资料
  18. 自兴人工智能 python特点了解
  19. Android RecyclerView预览item
  20. https协议为什么比http协议更加安全

热门文章

  1. 集成unittest做接口测试
  2. UIgradients – 美丽的UI渐变色分享站 并可转成CSS代码
  3. MySQL排序查询
  4. axios中then不用第二个参数,最好用catch
  5. codeforces Codeforces Round #597 (Div. 2) B. Restricted RPS 暴力模拟
  6. 每天进步一点点------Allegro 蛇形走线
  7. vue-cli 3 脚手架搭建(create)
  8. springboot引入Oracle依赖
  9. redis架构
  10. 如何预测股票分析--k-近邻