luogu P4197 Peaks

嘟嘟嘟


今天刷了一下NOI2018Day1的题,T1不会kruskal重构树就敲了60分暴力。
于是特意找了一条kruskal重构树板子刷一下。


这东西不难,感觉还挺有意思的。
这篇博客简明易懂:Kruskal重构树—学习笔记


对于这道题,我们建完重构树后,对于每一个询问,倍增向上跳到小于等于\(x\)且权值最大的点,然后就是查询这个点的子树内第\(k\)大的叶子节点的权值了。
因为一个子树内的dfs序是连续的,所以可以用主席树解决。dfs的时候继承节点\(u\)dfs序前一个的点。然后只有到叶子节点的时候再插入,其余情况直接继承树根。


对了,如果图不连通,那么就是一个森林了,得从每一个树根分别dfs。但这题的图似乎是连通的。
还有,这题没说清楚,应该是第\(k\)大的节点的权值,不是编号。恰巧样例里每一个点的权值和编号还是一样的,特别坑。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("") 
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 2e5 + 5;
const int maxm = 5e5 + 5;
const int maxN = 5e6 + 5;
const int N = 18;
inline ll read()
{
  ll ans = 0;
  char ch = getchar(), last = ' ';
  while(!isdigit(ch)) last = ch, ch = getchar();
  while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  if(last == '-') ans = -ans;
  return ans;
}
inline void write(ll x)
{
  if(x < 0) x = -x, putchar('-');
  if(x >= 10) write(x / 10);
  putchar(x % 10 + '0');
}

int n, m, q, ncnt;
int a[maxn], T[maxn], _n;
struct Node
{
  int x, y, w;
  In bool operator < (const Node& oth)const
  {
    return w < oth.w;
  }
}t[maxm];
struct Edge
{
  int nxt, to;
}e[maxn];
int head[maxn], ecnt = -1;
In void addEdge(int x, int y)
{
  e[++ecnt] = (Edge){head[x], y};
  head[x] = ecnt;
}

int p[maxn];
In int Find(int x) {return x == p[x] ? x : p[x] = Find(p[x]);}

int root[maxn];
int ls[maxN], rs[maxN], sum[maxN], tcnt;
In void insert(int old, int& now, int l, int r, int id, int pos)
{
  now = ++tcnt;
  ls[now] = ls[old], rs[now] = rs[old];
  sum[now] = sum[old] + 1;
  if(l == r) return;
  int mid = (l + r) >> 1;
  if(id <= mid) insert(ls[old], ls[now], l, mid, id, pos);
  else insert(rs[old], rs[now], mid + 1, r, id, pos);
}
In int query(int old, int now, int l, int r, int k)
{
  if(sum[now] < k) return -1;
  if(l == r) return l;
  int mid = (l + r) >> 1, Sum = sum[rs[now]] - sum[rs[old]];
  if(k <= Sum) return query(rs[old], rs[now], mid + 1, r, k);
  else return query(ls[old], ls[now], l, mid, k - Sum);
}

int dep[maxn], siz[maxn], dfsx[maxn], cnt = 0;
int fa[N + 2][maxn], Max[N + 2][maxn];
In void dfs(int now)
{
  dfsx[now] = ++cnt; siz[now] = 1;
  if(now <= n) insert(root[dfsx[now] - 1], root[dfsx[now]], 1, _n, a[now], now);
  else root[dfsx[now]] = root[dfsx[now] - 1];
  for(int i = 1; (1 << i) <= dep[now]; ++i)
    {
      fa[i][now] = fa[i - 1][fa[i - 1][now]];
      Max[i][now] = max(Max[i - 1][now], Max[i - 1][fa[i - 1][now]]);
    }
  for(int i = head[now], v; ~i; i = e[i].nxt)
    {
      dep[v = e[i].to] = dep[now] + 1;
      fa[0][v] = now, Max[0][v] = a[now];
      dfs(v);
      siz[now] += siz[v];
    }
}

In int solve(int x, int d)
{
  for(int i = N; i >= 0; --i)
    if(fa[i][x] && Max[i][x] <= d) x = fa[i][x];
  return x;
}

int main()
{
  //freopen("ha.in", "r", stdin);
  //freopen("ha.out", "w", stdout);
  Mem(head, -1);
  n = read(), m = read(), q = read();
  for(int i = 1; i <= n; ++i) a[i] = read(), p[i] = i;
  for(int i = 1; i <= m; ++i) t[i].x = read(), t[i].y = read(), t[i].w = read();
  sort(t + 1, t + m + 1);
  ncnt = n;
  for(int i = 1; i <= m; ++i)
    {
      int x = t[i].x, y = t[i].y;
      int px = Find(x), py = Find(y);
      if(px == py) continue;
      a[++ncnt] = t[i].w; p[ncnt] = ncnt;
      addEdge(ncnt, px), addEdge(ncnt, py);
      p[px] = ncnt, p[py] = ncnt;
    }
  for(int i = 1; i <= n; ++i) T[i] = a[i];
  sort(T + 1, T + n + 1);
  _n = unique(T + 1, T + n + 1) - T - 1;
  for(int i = 1; i <= n; ++i)
    a[i] = lower_bound(T + 1, T + _n + 1, a[i]) - T;
  dfs(ncnt);
  for(int i = 1; i <= q; ++i)
    {
      int v = read(), x = read(), K = read();
      v = solve(v, x);
      int ans = query(root[dfsx[v] - 1], root[dfsx[v] + siz[v] - 1], 1, _n, K);
      write(ans == -1 ? -1 : T[ans]), enter;
    }
  return 0;
}
posted @ 2019-04-30 15:14  mrclr  阅读(177)  评论(0编辑  收藏  举报