当前位置 博文首页 > ApocalypseTq的博客:P7834 [ONTAK2010] Peaks 加强版 题解

    ApocalypseTq的博客:P7834 [ONTAK2010] Peaks 加强版 题解

    作者:[db:作者] 时间:2021-09-23 15:47

    下面称?Kruscal?建树的时候的产生的点的权值为 “权值”,题目中给的点权称作 “贡献”。

    • 先是对于原图跑最小生成树的同时建立?Kruscal?重构树
    • 随后 dfs 遍历整棵树,维护好倍增数组以及给叶子节点(原图节点)编号,并且处理出每个非叶子节点?uu?为根的子树中包含的叶子节点的编号 最大 / 最小值。
    • 按照编号的顺序将叶子节点的 "贡献" 插入主席树中。
    • 查询的时候就倍增找到询问的点?uu?在树中最远的一个满足权值?\leq x≤x?的节点?pp(因为深度越浅,权值越大),它为根的子树里面任意一个点跟?uu?的?LCA?的权值一定会?\leq p≤p?的权值。
    • 求?pp?为根的子树中包含的叶子节点的 “贡献” 第?kk?大,因为编号连续,可以通过主席树区间查询。

    时间复杂度:O(m \log n + n \log n)O(mlogn+nlogn),空间复杂度:O(n \log n)O(nlogn)

    #include <bits/stdc++.h>
    using namespace std;
    inline int read() {
        int x = 0, flag = 1;
        char ch = getchar();
        for( ; ch > '9' || ch < '0' ; ch = getchar()) if(ch == '-') flag = -1;
        for( ; ch >= '0' && ch <= '9' ; ch = getchar()) x = (x << 3) + (x << 1) + ch - '0';
        return x * flag;
    }
    const int MAXN = 2e5 + 50, MAXM = 5e5 + 50;
    int n, m, f[MAXM + MAXN], tot, rt, start[MAXN], q, V[MAXN];
    int fa[MAXN][20], L[MAXN], dfn_id[MAXN], R[MAXN], dep[MAXN], A[MAXN], now = 0;
    int head, tail, Rt[MAXN], cnt = 0;
    vector <int> Son[MAXN];
    struct Edge {
        int from, to, w;
    } e[MAXM << 1];
    int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
    bool cmp(Edge a, Edge b) { return a.w < b.w; }
    struct SegmentTree {
        int ls, rs, Sum;
    } T[MAXN * 16];
    
    inline void DFS(int x, int from) {
        fa[x][0] = from, dep[x] = dep[from] + 1;
        L[x] = 1e9 + 7, R[x] = 0;
        for(int i = 1 ; i <= log2(dep[x]) ; i ++)
            fa[x][i] = fa[fa[x][i - 1]][i - 1];
        if(!Son[x].size()) L[x] = R[x] = ++ now, dfn_id[now] = x;
        for(int i = 0 ; i < Son[x].size(); i ++) {
            int to = Son[x][i];
            DFS(to, x);
            L[x] = min(L[to], L[x]);
            R[x] = max(R[to], R[x]);
        }
        return ;
    }
    inline int insert(int x, int l, int r, int pos) {
        int cur = ++ cnt, mid = (l + r) >> 1;
        T[cur] = T[x], T[cur].Sum ++;
        if(l == r) return cur;
        if(pos <= mid) T[cur].ls = insert(T[x].ls, l, mid, pos);
        else T[cur].rs = insert(T[x].rs, mid + 1, r, pos);
        return cur;
    }
    inline int Getfa(int x, int s) {
        for(int i = log2(dep[x]) ; i >= 0 ; i --)
            if(fa[x][i] != 0 && V[fa[x][i]] <= s) x = fa[x][i];
        return x;
    }
    inline int GetAns(int u, int v, int l, int r, int k) {
        int S = T[T[v].rs].Sum - T[T[u].rs].Sum, mid = (l + r) >> 1;
        if(l == r) return l;
        if(S >= k) return GetAns(T[u].rs, T[v].rs, mid + 1, r, k);
        else return GetAns(T[u].ls, T[v].ls, l, mid, k - S);
    }
    signed main() {
        //freopen("out","w",stdout);
        n = read(), m = read(), q = read(), rt = n;
        for(int i = 1 ; i <= n ; i ++) A[i] = read(); 
        for(int i = 1 ; i <= m ; i ++) {
            int u = read(), v = read(), w = read();
            e[i] = (Edge) { u, v, w };
        }
        for(int i = 1 ; i <= n + m ; i ++) f[i] = i;
        sort(e + 1, e + 1 + m, cmp);
        for(int i = 1 ; i <= m ; i ++) {
            int u = find(e[i].from), v = find(e[i].to);
            if(u != v) {
                rt ++, f[u] = f[v] = f[rt] = rt;
                V[rt] = e[i].w;
                Son[rt].push_back(u), Son[rt].push_back(v);
            }
        } DFS(rt, 0);
        int Ans = 0;
        for(int i = 1 ; i <= n ; i ++) 
            Rt[i] = insert(Rt[i - 1], 1, 1e9, A[dfn_id[i]]);
        for(int i = 1 ; i <= q ; i ++) {
            int u = (read() ^ Ans) % n + 1, x = read() ^ Ans, k = (read() ^ Ans) % n + 1;
            u = Getfa(u, x);
            if(R[u] - L[u] + 1 < k) Ans = 0, printf("-1\n");
            else Ans = GetAns(Rt[L[u] - 1], Rt[R[u]], 1, 1e9, k), printf("%d\n", Ans);
        }
        return 0;
    }

    cs
    下一篇:没有了