P4197 Peaks

\(\color{#0066ff}{题目描述}\)

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

\(\color{#0066ff}{输入格式}\)

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

\(\color{#0066ff}{输出格式}\)

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

\(\color{#0066ff}{输入样例}\)

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

\(\color{#0066ff}{输出样例}\)

6
1
-1
8

\(\color{#0066ff}{数据范围与提示}\)

\(N \leq 10^5, 0 \leq M, Q \leq 5 * 10^5, h_i, c, x \leq 10^9\)

\(\color{#0066ff}{题解}\)

Kruskal重构树

以困难程度为关键字建立大根堆

倍增找到最浅点

对于子树内的叶子,就是能到的所有点

找到这些点的第k大

考虑dfs序

只记录叶子节点的dfs序

同一子树内dfs序连续

用主席树维护就行了

#include<bits/stdc++.h>
#define LL long long
LL in() {
	char ch; int x = 0, f = 1;
	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
	return x * f;
}
const int maxn = 8e5 + 100;
struct tree {
protected:
	struct node {
		int num;
		node *ch[2];
		node(int num = 0): num(num) {
			ch[0] = ch[1] = NULL;
		}
		void *operator new (size_t) {
			static node *S = NULL, *T = NULL;
			return (S == T) && (T = (S = new node[1024]) + 1024), S++;
		}
	};
	node *root[maxn];
	void ins(node *&o, node *ls, int l, int r, int val) {
		o = new node();
		*o = *ls;
		o->num++;
		if(l == r) return;
		int mid = (l + r) >> 1;
		if(val <= mid) ins(o->ch[0], ls->ch[0], l, mid, val);
		else ins(o->ch[1], ls->ch[1], mid + 1, r, val);
	}
	int query(node *x, node *y, int l, int r, int k) {
		if(l == r) return l;
		int siz = y->ch[0]->num - x->ch[0]->num;
		int mid = (l + r) >> 1;
		if(k <= siz) return query(x->ch[0], y->ch[0], l, mid, k);
		else return query(x->ch[1], y->ch[1], mid + 1, r, k - siz);
	}
	void init() {
		root[0] = new node();
		root[0]->ch[0] = root[0]->ch[1] = root[0];
	}
public:
	tree() { init(); }
	void ins(int *s, int *t, int *m, int n, int len) {
		for(int i = 1; i <= n; i++) ins(root[i], root[i - 1], 1, len, std::lower_bound(t + 1, t + len + 1, s[m[i]]) - t);
	}
	int query(int l, int r, int k, int len) { return query(root[l - 1], root[r], 1, len, k); }
};
int n, m, q;
struct E {
	int x, y, z;
	bool operator < (const E &b) const {
		return z < b.z;
	}
}e[maxn];
struct node {
	int to;
	node *nxt;
	node(int to = 0, node *nxt = NULL): to(to), nxt(nxt) {}
	void *operator new (size_t) {
		static node *S = NULL, *T = NULL;
		return (S == T) && (T = (S = new node[1024]) + 1024), S++;
	}
};
node *head[maxn];
tree s;
int h[maxn], l[maxn], r[maxn], fa[maxn], hh[maxn], len = 1;
int findset(int x) { return x == fa[x]? fa[x] : fa[x] = findset(fa[x]); }
int f[maxn][26], dfn, redfn[maxn];
void add(int from, int to) {
	head[from] = new node(to, head[from]);
}
void dfs(int x, int ff) {
	f[x][0] = ff;
	if(x <= n) redfn[++dfn] = x;
	else l[x] = dfn + 1;
	for(node *i = head[x]; i; i = i->nxt) 
		if(i->to != ff) dfs(i->to, x);
	if(x > n) r[x] = dfn;
}
int query(int v, int x, int k) {
	for(int i = 24; i >= 0; i--) if(f[v][i] && h[f[v][i]] <= x) v = f[v][i];
	if(r[v] - l[v] + 1 < k) return -1;
	return hh[s.query(l[v], r[v], r[v] - l[v] + 2 - k, len)];
}
int main() {
	n = in(), m = in(), q = in();
	for(int i = 1; i <= n; i++) hh[i] = h[i] = in(), fa[i] = i;
	for(int i = 1; i <= m; i++) e[i].x = in(), e[i].y = in(), e[i].z = in();
	std::sort(hh + 1, hh + n + 1);
	std::sort(e + 1, e + m + 1);
	for(int i = 2; i <= n; i++) if(hh[i] != hh[i - 1]) hh[++len] = hh[i];
	int cnt = n, tot = 0;
	for(int i = 1; i <= m; i++) {
		int x = findset(e[i].x);
		int y = findset(e[i].y);
		if(x != y) {
			fa[x] = fa[y] = ++cnt;
			fa[cnt] = cnt;
			h[cnt] = e[i].z;
			add(cnt, x), add(cnt, y);
			tot++;
		}
		if(tot == n - 1) break;
	}
	dfs(cnt, 0);
	for(int j = 1; j <= 24; j++)
		for(int i = 1; i <= cnt; i++) 
			f[i][j] = f[f[i][j - 1]][j - 1];
	s.ins(h, hh, redfn, n, len);
	int v, x, k;
	while(q --> 0) {
		v = in(), x = in(), k = in();
		printf("%d\n", query(v, x, k));
	}
	return 0;
}
posted @ 2019-01-03 17:52  olinr  阅读(212)  评论(0编辑  收藏  举报