[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\n" , lastans = b[SGT.query(rt[v] , 1 , len , k)]);
        else printf("%d\n" , lastans = -1);
    }
    
    return 0;
}

 

posted @ 2019-02-13 22:53  evenbao  阅读(256)  评论(0编辑  收藏  举报