zoukankan      html  css  js  c++  java
  • Luogu 4197 Peaks

    BZOJ 3545 带权限。

    考虑离线,把所有边按照从小到大的顺序排序,把所有询问也按照从小到大的顺序排序,然后维护一个并查集和一个权值线段树,每处理一个询问就把比这个询问的$x$更小的边连上,具体来说就是合并两个并查集以及两棵线段树,查询的时候在线段树上走一走就好了。

    要注意查询的第$k$大不是第$k$小,所以顺便再维护一个$siz$,如果$siz < k$那答案即为$-1$。

    时间复杂度$O((m + q)logn)$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N = 1e5 + 5;
    const int M = 5e5 + 5;
    const int inf = 1 << 30;
    
    int n, m, qn, a[N], mn = 0, mp[N], ufs[N], siz[N];
    
    struct Innum {
        int val, id;
        
        friend bool operator < (const Innum &x, const Innum &y) {
            if(x.val == y.val) return x.id < y.id;
            else return x.val < y.val;
        }
        
    } in[N];
    
    struct Pathway {
        int u, v, val;
        
        friend bool operator < (const Pathway &x, const Pathway &y) {
            return x.val < y.val;
        }
        
    } path[M];
    
    struct Querys {
        int pos, val, k, id, res;
        
        friend bool operator < (const Querys &x, const Querys &y) {
            return x.val < y.val;
        }
        
    } q[M];
    
    inline void read(int &X) {
        X = 0; char ch = 0; int op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    inline void chkMax(int &x, int y) {
        if(y > x) x = y;
    }
    
    inline void discrete() {
        sort(in + 1, in + 1 + n);
        in[0].val = -inf;
        for(int cnt = 0, i = 1; i <= n; i++)  {
            if(in[i].val != in[i - 1].val) ++cnt;
            chkMax(mn, cnt);
            a[in[i].id] = cnt;
            mp[cnt] = in[i].val;
        }
    } 
    
    namespace PSegT {
        struct Node {
            int lc, rc, sum;
        } s[N * 60];
        
        int root[N], nodeCnt = 0, top = 0, pool[N * 60];
        
        #define lc(p) s[p].lc
        #define rc(p) s[p].rc
        #define sum(p) s[p].sum
        #define mid ((l + r) >> 1) 
        
        inline void push(int x) {
            pool[++top] = x;
        }
        
        inline int newNode() {
            if(top) return pool[top--];
            else return ++nodeCnt;
        }
        
        void ins(int &p, int l, int r, int x) {
            if(!p) p = newNode();
            ++sum(p);
            if(l == r) return;
            
            if(x <= mid) ins(lc(p), l, mid, x);
            else  ins(rc(p), mid + 1, r, x);
        }
        
        int go(int p, int l, int r, int x) {
            if(l == r) return sum(p);
            
            if(x <= mid) return go(lc(p), l, mid, x);
            else return go(rc(p), mid + 1, r, x);
        }
        
        int query(int p, int l, int r, int k)  {
            if(l == r) return mp[l];
            int now = sum(lc(p));
            
            if(k <= now) return query(lc(p), l, mid, k);
            else return query(rc(p), mid + 1, r, k - now);
        }
        
        int merge(int u, int v, int l, int r) {
            if(!u || !v) return u + v;
            
            int p = newNode();
            if(l == r) sum(p) = sum(u) + sum(v);
            else {
                lc(p) = merge(lc(u), lc(v), l, mid);
                rc(p) = merge(rc(u), rc(v), mid + 1, r);
                sum(p) = sum(lc(p)) + sum(rc(p));
            }
            
            push(u), push(v);
            return p;
        }
        
    } using namespace PSegT;
    
    inline void init() {
        for(int i = 1; i <= n; i++) {
            ufs[i] = i;
            siz[i] = 1;
            ins(root[i], 1, mn, a[i]);
        }
    }
    
    int find(int x) {
        return ufs[x] == x ? x : ufs[x] = find(ufs[x]);
    }
    
    inline void merge(int x, int y) {
        int fx = find(x), fy = find(y);
        if(fx == fy) return;
        root[fx] = merge(root[fx], root[fy], 1, mn);
        ufs[fy] = fx;
        siz[fx] += siz[fy];
        
    /*    for(int i = 1; i <= mn; i++)
            printf("%d ", go(root[fx], 1, mn, i));
        printf("
    ");    */
    }
    
    int main()  {
        read(n), read(m), read(qn); 
        for(int i = 1; i <= n; i++) {
            read(a[i]);
            in[i].val = a[i], in[i].id = i;
        }
        for(int i = 1; i <= m; i++) 
            read(path[i].u), read(path[i].v), read(path[i].val);
        for(int i = 1; i <= qn; i++) 
            read(q[i].pos), read(q[i].val), read(q[i].k), q[i].id = i;
        
        sort(path + 1, path + 1 + m), sort(q + 1, q + 1 + qn);
        
    /*    printf("
    ");
        for(int i = 1; i <= m; i++)
            printf("%d %d %d
    ", path[i].u, path[i].v, path[i].val);
        printf("
    ");
        for(int i = 1; i <= qn; i++)
            printf("%d %d %d
    ", q[i].pos, q[i].val, q[i].k);
        printf("
    ");      */
        
        discrete();
        init();
        
    /*    for(int i = 1; i <= n; i++)
            printf("%d ", a[i]);
        printf("
    ");    */
        
        for(int j = 1, i = 1; i <= qn; i++) {
            for(; j <= m && path[j].val <= q[i].val; ++j)
                merge(path[j].u, path[j].v);
            int now = find(q[i].pos);
            
    /*        for(int k = 1; k <= mn; k++)
                printf("%d ", go(root[now], 1, mn, k));
            printf("
    ");     */
            
            if(q[i].k > siz[now]) q[q[i].id].res = -1;
            else q[q[i].id].res = query(root[now], 1, mn, siz[now] - q[i].k + 1);
        }
        
        for(int i = 1; i <= qn; i++)
            printf("%d
    ", q[i].res);
        
        return 0;
    }
    View Code
  • 相关阅读:
    POJ 2528 Mayor's posters(线段树)
    Codeforces Beta Round #22 (Div. 2 Only) C. System Administrator(构造割点)
    HDU 4417 Super Mario(划分树)
    Codeforces Beta Round #22 (Div. 2 Only) D. Segments(贪心)
    HDU 1247 Hat’s Words(字典树)
    HDU 3639 HawkandChicken(强连通分量)
    HDU 3394 Railway(点双连通分量)
    HDU 1394 Minimum Inversion Number(树状数组)
    HDU 3874 Necklace(树状数组+离线处理)
    树状数组
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9717879.html
Copyright © 2011-2022 走看看