zoukankan      html  css  js  c++  java
  • Luogu P4197.Peaks

    题目

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

    解法

    非常经典的解法
    考虑 (Kruskal) 重构树的性质,然后对于一个子树求第 (k) 大,主席树就行了

    (Code)

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    const int N = 2e5 + 5, INF = 0x3f3f3f3f;
    int n, m, q, a[N], L = INF, R = -INF;
    
    inline void read(int &x)
    {
    	x = 0; int f = 1; char ch = getchar();
    	while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : f), ch = getchar();
    	while (ch >= '0' && ch <= '9') x = (x<<3)+(x<<1)+ch-'0', ch = getchar();
    	x *= f;
    }
    
    int h[N], tot;
    struct edge{int to, nxt;}e[N];
    inline void add(int x, int y){e[++tot] = edge{y, h[x]}, h[x] = tot;}
    
    int fa[N];
    int find(int x){return (fa[x] == x ? x : (fa[x] = find(fa[x])));}
    
    int val[N], num;
    struct Edge{int u, v, w;}E[3 * N];
    inline bool cmp(Edge x, Edge y){return x.w < y.w;}
    void Kruskal()
    {
    	sort(E + 1, E + m + 1, cmp);
    	for(register int i = 1; i < 2 * n; i++) fa[i] = i;
    	num = n;
    	for(register int i = 1; i <= m; i++)
    	{
    		int tx = find(E[i].u), ty = find(E[i].v);
    		if (tx ^ ty)
    		{
    			fa[tx] = fa[ty] = ++num, val[num] = E[i].w;
    			add(num, tx), add(num, ty);
    			if (num == 2 * n - 1) break;
    		}
    	}
    }
    
    int siz[N], dfn[N], rev[N], ed[N], dfc, f[N][20];
    void dfs(int x)
    {
    	if (x <= n) siz[x] = 1, dfn[x] = ++dfc, rev[dfc] = x;
    	for(register int i = 1; i <= 18; i++)
    	if (f[x][i - 1]) f[x][i] = f[f[x][i - 1]][i - 1];
    	else break;
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (v == fa[x]) continue;
    		fa[v] = x, f[v][0] = x, dfs(v), siz[x] += siz[v];
    	}
    	ed[x] = dfc;
    }
    inline int getup(int u, int lim, int k)
    {
    	for(register int i = 18; i >= 0; --i)
    	if (f[u][i] && val[f[u][i]] <= lim) u = f[u][i];
    	if (siz[u] < k) return -1;
    	return u;
    }
    
    int size, rt[N];
    struct node{int sum, ls, rs;}seg[N * 32];
    void update(int &u, int v, int l, int r, int x)
    {
    	u = ++size;
    	seg[u] = seg[v], ++seg[u].sum;
    	if (l == r) return;
    	int mid = (l + r) >> 1;
    	if (x <= mid) update(seg[u].ls, seg[v].ls, l, mid, x);
    	else update(seg[u].rs, seg[v].rs, mid + 1, r, x);
    }
    int query(int u, int v, int l, int r, int k)
    {
    	if (l == r) return l;
    	int mid = (l + r) >> 1, s = seg[seg[u].rs].sum - seg[seg[v].rs].sum;
    	if (k <= s) return query(seg[u].rs, seg[v].rs, mid + 1, r, k);
    	return query(seg[u].ls, seg[v].ls, l, mid, k - s);
    }
    
    int main()
    {
    	read(n), read(m), read(q);
    	for(register int i = 1; i <= n; i++) read(a[i]), L = min(L, a[i]), R = max(R, a[i]);
    	for(register int i = 1; i <= m; i++) read(E[i].u), read(E[i].v), read(E[i].w);
    	Kruskal(), memset(fa, 0, sizeof fa), dfs(num);
    	for(register int i = 1; i <= n; i++) update(rt[i], rt[i - 1], L, R, a[rev[i]]);
    	for(int v, x, k; q; --q)
    	{
    		read(v), read(x), read(k);
    		int up = getup(v, x, k);
    		printf("%d
    ", (up == -1 ? -1 : query(rt[ed[up]], rt[ed[up] - siz[up]], L, R, k)));
    	}
    }
    
  • 相关阅读:
    easyExcel入门
    UML-从需求到设计--迭代进化
    UML-操作契约总结
    102. Binary Tree Level Order Traversal
    98. Validate Binary Search Tree
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees
    94. Binary Tree Inorder Traversal
    84. Largest Rectangle in Histogram
    92. Reverse Linked List II
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/14332723.html
Copyright © 2011-2022 走看看