zoukankan      html  css  js  c++  java
  • [BZOJ 3551] Peaks加强版

    [题目链接]

            https://www.lydsy.com/JudgeOnline/problem.php?id=3551

    [算法]

            建出此图的kruskal重构树

            用线段树合并维护每个联通块的第k大点权

            这样就可以在线回答询问了

            时间复杂度 : O((N + Q)log N)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 10;
    const int M = 5e5 + 10;
    const int MAXLOG = 17;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    #define rint register int
    
    struct info
    {
        int u , v , w;
    } a[M];
    
    int n , m , q , tot , len , cnt;
    int head[N << 1] , h[N] , b[N] , fa[N << 1] , size[N << 1] , depth[N << 1] , rt[N << 1] , value[N << 1];
    int father[N << 1][MAXLOG];
    
    struct Segment_Tree 
    {
        int sz;
        struct node
        {
            int lc , rc;
            int cnt;
        } a[N * 60];
        Segment_Tree()
        {
            sz = 0;
        }
        inline void update(int now)
        {
            a[now].cnt = a[a[now].lc].cnt + a[a[now].rc].cnt;
        }
        inline void modify(int &now , int l , int r , int x , int value)
        {
            if (!now) now = ++sz;
            if (l == r) 
            {
                a[now].cnt += value;
                return;
            }
            int mid = (l + r) >> 1;
            if (mid >= x) modify(a[now].lc , l , mid , x , value);
            else modify(a[now].rc , mid + 1 , r , x , value);
            update(now);
        }
        inline int merge(int x , int y , int l , int r)
        {
            if (x == 0 || y == 0) 
                return x + y;
            int p = ++sz;
            a[p].cnt = a[x].cnt + a[y].cnt;
            int mid = (l + r) >> 1;
            a[p].lc = merge(a[x].lc , a[y].lc , l , mid);
            a[p].rc = merge(a[x].rc , a[y].rc , mid + 1 , r);
            return p;
        }
        inline int query(int now , int l , int r , int k)
        {
            if (l == r) return l;
            int mid = (l + r) >> 1;
            if (a[a[now].rc].cnt >= k) return query(a[now].rc , mid + 1 , r , k);
            else return query(a[now].lc , l , mid , k - a[a[now].rc].cnt);
        }
    } SGT;
    
    template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
    template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
    template <typename T> inline void read(T &x)
    {
       T f = 1; x = 0;
       char c = getchar();
       for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
       for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
       x *= f;
    }
    inline bool cmp(info a , info b)
    {
        return a.w < b.w;
    }
    inline int getroot(int x)
    {
        if (fa[x] == x) return x;
        else return fa[x] = getroot(fa[x]);
    }
    inline void kruskal()
    {
        int tot = 0;
        cnt = n;
        for (rint i = 1; i <= 2 * n; i++) fa[i] = i;
        for (rint i = 1; i <= m; i++)
        {        
            int fu = getroot(a[i].u) , fv = getroot(a[i].v);
            if (fu != fv)
            {
                father[fu][0] = father[fv][0] = ++cnt;
                value[cnt] = a[i].w;
                rt[cnt] = SGT.merge(rt[fu] , rt[fv] , 1 , len);
                fa[fu] = fa[fv] = fa[cnt] = cnt;
                ++tot;
            } 
            if (tot == n - 1) break;
        } 
        for (int i = 1; i < MAXLOG; i++)
        {
            for (int j = 1; j <= cnt; j++)
            {
                father[j][i] = father[father[j][i - 1]][i - 1];
            }
        }
    }
    
    int main()
    {
    
        read(n); read(m); read(q);
        for (rint i = 1; i <= n; i++) 
        {
            read(h[i]);
            b[i] = h[i];
        }
        sort(b + 1 , b + n + 1);
        len = unique(b + 1 , b + n + 1) - b - 1;
        for (rint i = 1; i <= n; i++) h[i] = lower_bound(b + 1 , b + len + 1 , h[i]) - b;
        for (rint i = 1; i <= n; i++) SGT.modify(rt[i] , 1 , len , h[i] , 1);
        for (rint i = 1; i <= m; i++)
        {
            read(a[i].u); 
            read(a[i].v); 
            read(a[i].w);
        }    
        sort(a + 1 , a + m + 1 , cmp);
        kruskal();
        int lastans = 0;
        while (q--)
        {
            int v , x , k;
            read(v); read(x); read(k);
            if (lastans != -1)
            {
                v ^= lastans;
                x ^= lastans;
                k ^= lastans;
            }
            for (rint i = MAXLOG - 1; i >= 0; i--)
            {
                if (father[v][i] && value[father[v][i]] <= x)
                    v = father[v][i];    
            }    
            if (SGT.a[rt[v]].cnt >= k) printf("%d
    " , lastans = b[SGT.query(rt[v] , 1 , len , k)]);
            else printf("%d
    " , lastans = -1);
        }
        
        return 0;
    }
  • 相关阅读:
    谷粒商城学习——P41vue组件化
    谷粒商城学习——P40计算属性、侦听器、过滤器
    谷粒商城学习——P38-39Vue-指令-单向绑定&双向绑定&v-onv-forv-if
    谷粒商城学习——P37vue基本语法——双向绑定、事件处理
    谷粒商城学习——P36Vue介绍与HelloWord
    谷粒商城学习——P35模块化
    谷粒商城学习——P34Promise异步编排
    Windows tcp/ip(CVE-2020-16898)远程代码执行蓝屏漏洞复现
    QQ群关系可视化3D查询搭建
    Skywalking 8.1 Docker 服务端部署
  • 原文地址:https://www.cnblogs.com/evenbao/p/10372276.html
Copyright © 2011-2022 走看看