[HNOI 2012] 永无乡

[题目链接]

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

[算法]

        用线段树维护图的联通块 , 并查集维护连通性

        加边时可以直接线段树合并

        时间复杂度 : O(NlogN)

[代码]

        

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010 
#define MAXP 10000010
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

int n , m;
int fa[MAXN] , rt[MAXN] , rk[MAXN] , rev[MAXN];

struct Segment_Tree
{
        int sz;
        Segment_Tree()
        {
                sz = 0;
        }
        struct Node
        {
                int cnt;
                int lc , rc;
        } a[MAXP];
        inline int merge(int x , int y)
        {
                if (x == 0 || y == 0) return x + y;
                a[x].cnt += a[y].cnt;
                a[x].lc = merge(a[x].lc , a[y].lc);
                a[x].rc = merge(a[x].rc , a[y].rc);
                return x;
        }
        inline void update(int x)
        {
                a[x].cnt = a[a[x].lc].cnt + a[a[x].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 = 1;
                        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 query(int &now , int l , int r , int k)
        {
                if (!now) now = ++sz;
                if (l == r) return l;
                int mid = (l + r) >> 1;
                if (a[a[now].lc].cnt >= k) return query(a[now].lc , l , mid , k);
                else return query(a[now].rc , mid + 1 , r , k - a[a[now].lc].cnt);
        }
        inline int query(int now , int k)
        {
                if (a[rt[now]].cnt < k) return -1;
                else return query(rt[now] , 1 , n , k);
        }
} SGT;

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(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 int get_root(int x)
{
        if (fa[x] == x) return x;
        else return fa[x] = get_root(fa[x]);
}

int main()
{
        
        scanf("%d%d" , &n , &m);
        for (int i = 1; i <= n; i++) 
        {
                scanf("%d" , &rk[i]);
                rev[rk[i]] = i;
        }
        for (int i = 1; i <= n; i++) 
        {
                fa[i] = i;
                rt[i] = 0;
        }
        for (int i = 1; i <= n; i++) SGT.modify(rt[i] , 1 , n , rk[i] , 1);
        for (int i = 1; i <= m; i++)
        {
                int x , y;
                scanf("%d%d" , &x , &y);
                if (get_root(x) != get_root(y))
                {
                        rt[get_root(y)] = SGT.merge(rt[get_root(x)] , rt[get_root(y)]);
                        fa[get_root(x)] = get_root(y);
                }
        }
        int q;
        scanf("%d" , &q);
        while (q--)
        {
                char type[5];
                scanf("%s" , type);
                if (type[0] == 'Q')
                {
                        int x , k;
                        scanf("%d%d" , &x , &k);
                        int tmp = SGT.query(get_root(x) , k);
                        if (tmp == -1) printf("-1\n");    
                        else printf("%d\n" , rev[tmp]);    
                }    else
                {
                        int x , y;
                        scanf("%d%d" , &x , &y);
                        if (get_root(x) != get_root(y))
                        {
                                rt[get_root(y)] = SGT.merge(rt[get_root(x)] , rt[get_root(y)]);
                                fa[get_root(x)] = get_root(y);
                        }        
                }    
        }
        
        return 0;
    
}

猜你喜欢

转载自www.cnblogs.com/evenbao/p/10203407.html
今日推荐