• 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;
    }
    
  • 相关阅读:
    vue-element-admin中table分页改为前台处理
    vue项目如何部署到Tomcat中
    vuex之modules 热加载(hot update)
    持续学习
    css比较特殊选择器汇总(持续更新)
    关于伪元素before after总结
    ajax入门-实现省份下拉框
    super和this关键字的详解
    监听器
    当浏览器被关闭时,session是否被关闭?
  • 原文地址:https://www.cnblogs.com/mrclr/p/10796148.html
Copyright © 2020-2023  润新知