这道题很好想, 离线, 按询问的x排序从小到大, 然后用并查集维护连通性, 用平衡树维护连通块的山的权值, 合并就用启发式合并.时间复杂度的话, 排序是O(mlogm + qlogq), 启发式合并是O(nlog²n), 询问是O(qlogn).

-------------------------------------------------------------------

#include<bits/stdc++.h>
 
#define rep(i, n) for(int i = 0; i < n; ++i)
#define clr(x, c) memset(x, c, sizeof(x))
 
using namespace std;
 
const int maxn = 100009;
const int maxq = 500009;
 
struct Node {
Node* ch[2];
int s, r, v;
Node():r(rand()) {}
inline void upd() {
s = ch[0]->s + ch[1]->s + 1;
}
} pool[maxn * 20], *pt = pool, *root[maxn], *null;
 
Node* newNode(int v) {
pt->ch[0] = pt->ch[1] = null;
pt->s = 1, pt->v = v;
return pt++;
}
 
void init() {
null = pt++;
null->s = 0;
null->ch[0] = null->ch[1] = null;
}
 
void rotate(Node* &t, int d) {
Node* h = t->ch[d ^ 1];
t->ch[d ^ 1] = h->ch[d];
h->ch[d] = t;
t->upd(), h->upd();
t = h;
}
 
void insert(Node* &t, int v) {
if(t == null) 
   t = newNode(v);
else {
int d = v <= t->v;
insert(t->ch[d], v);
if(t->ch[d]->r > t->r) rotate(t, d ^ 1);
}
t->upd();
}
 
void del(Node* &t, int v) {
int d = v == t->v ? -1 : v < t->v;
if(d == -1) {
if(t->ch[0] != null && t->ch[1] != null) {
int h = t->ch[0]->r > t->ch[1]->r;
rotate(t, h), del(t->ch[h], v);
} else
   t = t->ch[0] == null ? t->ch[1] : t->ch[0];
} else
   del(t->ch[d], v);
if(t != null) t->upd();
}
 
int select(Node*t, int k) {
if(k > t->s) return -1;
for(; ;) {
int s = t->ch[0]->s;
if(k == s + 1) return t->v;
if(k > s)
   k -= s + 1, t = t->ch[1];
else
   t = t->ch[0];
}
}
 
inline int read() {
char c = getchar();
for(; !isdigit(c); c = getchar());
int ans = 0;
for(; isdigit(c); c = getchar())
   ans = ans * 10 + c - '0';
return ans;
}
 
int p[maxn];
 
int find(int x) {
return x == p[x] ? x : p[x] = find(p[x]);
}
 
inline void unite(int x, int y) {
int a = find(x), b = find(y);
p[a] = b;
if(root[a] != root[b]) {
if(root[a]->s > root[b]->s) swap(a, b);
while(root[a] != null) {
insert(root[b], root[a]->v);
del(root[a], root[a]->v);
}
root[a] = root[b];
}
}
 
struct Q {
int x, lim, k, pos;
inline void Read(int p) {
x = read() - 1, lim = read(), k = read(), pos = p;
}
bool operator < (const Q &t) const {
return lim < t.lim;
}
} A[maxq];
 
struct edge {
int u, v, w;
inline void Read() {
u = read() - 1, v = read() - 1, w = read();
}
bool operator < (const edge &e) const {
return w < e.w;
}
} E[maxq];
 
int ans[maxq];
 
int main() {
freopen("test.in", "r", stdin);
init();
int n, m, q, _p = 0;
cin >> n >> m >> q;
rep(i, n) root[i] = newNode(read());
rep(i, n) p[i] = i;
rep(i, m) E[i].Read(); sort(E, E + m);
rep(i, q) A[i].Read(i); sort(A, A + q);
rep(i, q) {
Q* h = A + i;
for(; E[_p].w <= h->lim && _p < m; _p++) unite(E[_p].u, E[_p].v);
ans[h->pos] = select(root[find(h->x)], h->k);
}
rep(i, q) printf("%d\n", ans[i]);
return 0;
}

-------------------------------------------------------------------

3545: [ONTAK2010]Peaks

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 816  Solved: 231
[Submit][Status][Discuss]

Description

在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。

Input

第一行三个数N,M,Q。
第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。

Output

对于每组询问,输出一个整数表示答案。

Sample Input

10 11 4
1 2 3 4 5 6 7 8 9 10
1 4 4
2 5 3
9 8 2
7 8 10
7 1 4
6 7 1
6 4 8
2 1 5
10 8 10
3 4 7
3 4 6
1 5 2
1 5 6
1 5 8
8 9 2

Sample Output

6
1
-1
8

HINT

【数据范围】

N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。

Source

BZOJ 3545: [ONTAK2010]Peaks( BST + 启发式合并 + 并查集 )的更多相关文章

  1. BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]

    3545: [ONTAK2010]Peaks 题意:带权图,多组询问与一个点通过边权\(\le x\)的边连通的点中点权k大值 又读错题了,输出点一直WA,问的是点权啊 本题加强版强制在线了,那这道题 ...

  2. BZOJ.3545.[ONTAK2010]Peaks(线段树合并)

    题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. \(Solut ...

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

    不难...treap + 启发式合并 + 并查集 搞搞就行了 --------------------------------------------------------------------- ...

  4. BZOJ 4668 冷战(按秩合并并查集+LCA)

    4668: 冷战 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 627  Solved: 303[Submit][Status][Discuss] D ...

  5. bzoj 3545: [ONTAK2010]Peaks

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1124  Solved: 304[Submit][Status][Discuss] Descripti ...

  6. BZOJ 2733 [HNOI2012]永无乡 (权值线段树启发式合并+并查集)

    题意: n<=1e5的图里,在线连边.查询某连通块第k大 思路: 练习线段树合并的好题,因为依然记得上一次启发式合并trie的时候内存爆炸的恐怖,所以这次还是用了动态开点.回收 听说启发式合并s ...

  7. 【BZOJ1483】[HNOI2009]梦幻布丁(平衡树启发式合并+并查集)

    题目: BZOJ1483 分析: (这题码了一下午,码了近250行,但是意外跑的比本校各位神仙稍快,特写博客纪念) 首先能看出一个显然的结论:颜色段数只会变少不会变多. 我们考虑用并查集维护区间,对于 ...

  8. 【bzoj2733】永无乡(无旋treap启发式合并 + 并查集)

    传送门 题目分析 起初每个岛都是一个平衡树, 并查集的祖先都是自己.合并两岛时,pri较小的祖先会被作为合并后的祖先, 而两颗平衡树采用启发式合并.查询k值就是基本操作. code #include& ...

  9. BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay

    Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询 ...

随机推荐

  1. Ubuntu中文输入法

    这里是Ubuntu12.04,刚把系统语言设成英文,发现输入法没有了. 看看下面是如何找回来的吧. Ubuntu上的输入法主要有小小输入平台(支持拼音/二笔/五笔等),Fcitx,Ibus,Scim等 ...

  2. open和fopen的区别:

    1.缓冲文件系统缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用,当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”, 装满后再从内存“缓冲区”依此读入接收的变量.执行 ...

  3. VC程序快速删除自己(可能做升级程序的时候有用)

    项目一般都会带有卸载程序,如果这个程序是自己来做的话,在调用完卸载程序后需要删除自己的所有文件,在Google了好久终于找到一些相关信息,一般只能删除一个文件,经过自己的处理,可以删除文件夹下面所有内 ...

  4. 破解企业QQ对个人QQ登陆的限制(原创)

    运行系统:WIN7 破解时间:2014-02-19 破解思路:自从2013-11-11的1.85版企业qq更新后,网上流传的破解方法(运行文件BeatQQEIM.bat)已经不起作用了,可以同时登陆, ...

  5. TTL电平与RS232电平的区别

    TTL电平与RS232电平的区别   工作中遇到一个关于电平选择的问题,居然给忘记RS232电平的定义了,当时无法反应上来,回来之后查找资料才了解两者之间的区别,视乎两年多的时间,之前非常熟悉的一些常 ...

  6. CentOS6.5 下在Nginx中添加SSL证书以支持HTTPS协议访问

    参考文献: 1. NginxV1.8.0安装与配置 2. CentOS下在Nginx中添加SSL证书以支持HTTPS协议访问 3. nginx配置ssl证书的方法 4.nginx强制使用https访问 ...

  7. ZOJ2971 Give Me the Number 【模拟】

    这道题目使用Map. 然后一次性遍历下来即可. QAQ 注意初始化的时候小心点不要错.. Source Code: //#pragma comment(linker, "/STACK:167 ...

  8. struts2--配置文件中使用通配符

    struts2的配置文件是 struts.xml.. 在这个配置文件里面可以使用通配符..其中的好处就是,大大减少了配置文件的内容..当然,相应付出的代价是可读性.. 使用通配符的原则是 约定高于配置 ...

  9. UIScrollView方法 属性详解

    --前言:UIScrollView使用非常广,本文研究UIScrollView各属性和方法,明白它们的意义.作用.在后面的一篇文章有整理UIScrollView一些常见用法以及一些效果的实现思路. - ...

  10. 基于visual Studio2013解决算法导论之050强连通分支

     题目 强连通分支 解决代码及点评 // 强连通分支.cpp : 定义控制台应用程序的入口点. // #include<iostream> #define MAX 100 using ...