标签:一个 roo col 题目 bool mount 输入 lin 倍增
在Bytemountains有N座山峰,每座山峰有他的高度\(h_i\) 。有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个困难值,这个值越大表示越难走,现在有\(Q\)组询问,每组询问询问从点\(v\)开始只经过困难值小于等于\(x\)的路径所能到达的山峰中第\(k\)高的山峰,如果无解输出\(-1\)。
第一行三个数\(N,M,Q\)。 第二行\(N\)个数,第i个数为\(h_i\) 接下来\(M\)行,每行\(3\)个数\(a,b,c\),表示从\(a\)到\(b\)有一条困难值为\(c\)的双向路径。 接下来\(Q\)行,每行三个数\(v,x,k\) 表示一组询问。
对于每组询问,输出一个整数表示答案。
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
6
1
-1
8
\(N \leq 10^5, 0 \leq M, Q \leq 5 * 10^5, h_i, c, x \leq 10^9\)
#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;
}
标签:一个 roo col 题目 bool mount 输入 lin 倍增
原文地址:https://www.cnblogs.com/olinr/p/10215947.html