传送门

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\)

「HNOI2012」永无乡的更多相关文章

  1. 「BZOJ2733」「洛谷3224」「HNOI2012」永无乡【线段树合并】

    题目链接 [洛谷] 题解 很明显是要用线段树合并的. 对于当前的每一个连通块都建立一个权值线段树. 权值线段树处理操作中的\(k\)大的问题. 如果需要合并,那么就线段树暴力合并,时间复杂度是\(nl ...

  2. BZOJ2733/LG3324 「HNOI2014」永无乡 权值线段树合并

    问题描述 BZOJ2733 LG3224 题解 对于每个结点建立一棵权值线段树. 查询操作就去查询第 \(k\) 大,合并操作就合并两颗权值线段树. 并查集维护连通性. 同时 STO hkk,zcr, ...

  3. BZOJ 2733 【HNOI2012】 永无乡

    Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以 ...

  4. 【HNOI2012】永无乡(splay,启发式合并)

    题解 Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过 ...

  5. 【BZOJ2733】【HNOI2012】永无乡 - 线段树合并

    题意: Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通 ...

  6. 「BZOJ 2733」「HNOI 2012」永无乡「启发式合并」

    题意 你需要维护若干连通快,有两个操作 合并\(x,y\)所在的连通块 询问\(x\)所在连通块中权值从小到大排第\(k\)的结点编号 题解 可以启发式合并\(splay\),感觉比较好些的 一个连通 ...

  7. 【BZOJ】【2733】【HNOI2012】永无乡

    平衡树+启发式合并+并查集 因为要求一坨数中第k大的……用平衡树会很好维护…… 但又要求连通块?所以用并查集来维护…… 大概就是让并查集的fa和Treap的根是同一个节点吧…… TLE了N多发,可能是 ...

  8. 【BZOJ2733】【HNOI2012】永无乡

    原题传送门 题意:给你N个带权点,一开始相互独立(每个点视为单独一个集合),有2种操作:1)合并2个集合:2)查询包含某元素集合内的权值第k小点编号. 解题思路:显然合并就是并查集,而查询则是平衡树实 ...

  9. 【HNOI2012】永无乡 题解(并查集+线段树合并)

    题目链接 给定一张含$n$个点$m$条边的无向图,每个点有一个重要指数$a_i$.有两种操作:1.在$x$和$y$之间连一条边:2.求$x$所在连通块中重要程度第$k$小的点. ----------- ...

随机推荐

  1. mysql update某个字段替换成某个值

    UPDATE xc_admin_vehicle SET brandid= REPLACE(brandid, 19, 54) UPDATE xc_admin_models SET bid= REPLAC ...

  2. 掩膜(mask)

    1.掩膜(mask)的定义 用选定的图像,图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程.用于覆盖的特定图像或物体称为掩模或模板.光学图像处理中,掩模可以足胶片,滤光片 ...

  3. Java-POJ1009-Edge Detection(未完成,有C++代码)

    RLE编码,还不会,先搬运一下大佬的代码,理解之后再用Java自己实现 #include <map> #include <vector> #include <cstdli ...

  4. 微信h5游戏如何在微信中做好域名防封 防屏蔽的 工作

    最近微信开始大封杀,不知道原因是什么,可能是因为违规网站太多了吧,很多网站都被错杀了,下面我们聊一下怎样才能避免域名被封杀呢. 在各种不同的域名当中,能够做出了更适合的选择,这些对于大家域名防封_域名 ...

  5. Iris路由和路由组

    package main import ( "github.com/kataras/iris" "github.com/kataras/iris/context" ...

  6. codeforces Make The Fence Great Again(dp)

    题目链接:http://codeforces.com/contest/1221/problem/D 题目要求ai ! = ai-1,草纸上推理一下可以发现每一个栅栏可以升高的高度无非就是 +0,+1, ...

  7. 剑指offer面试题30.包含min函数的栈

    一开始写的垃圾代码,push和pop都是O(N) class Solution { public: vector<int> vec; int min_val=INT_MAX,min_cnt ...

  8. Codeforces Global Round 3:B. Born This Way

    Born This Way原文链接:[传送门] 题目大意:潇洒哥想乘坐飞机从A地到达C地,但是没有直达的航班,在A地和B地之间有一个可以中转的航班B,潇洒哥想早点到达C地(有航班就坐),但是很不幸他得 ...

  9. Git的基本使用 -- 创建本地仓库

    下载安装 Git-2.25.0-64-bit .exe 查看是否安装成功 git --version 创建本地仓库 创建一个文件夹用于存放项目文件 在创建好的文件中右键选择 Git Bash Here ...

  10. 深入理解JDK、JRE(两套)、JVM、以及不同目录下的java.exe

    内容来自:http://blog.sina.com.cn/s/blog_7ffb8dd501011sgc.html 1.jdk下bin目录里的java.exe与外部jre中的java.exe的秘密   ...