P3224 [HNOI2012]永无乡(线段树合并 时间复杂度 nlogn)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 30000005;
int tree[maxn],lc[maxn],rc[maxn],tot,sum[maxn];
void push_up( int x ){
    tree[x] = max( tree[ lc[x] ],tree[rc[x] ] );
    sum[x] = sum[ lc[x] ] + sum[ rc[x] ];
}
void update( int left,int right,int v,int l,int r,int x ){
    if( left <= l && right >= r ){
        tree[x] = v;sum[x] = 1;
        return;
    }
    int mid = l+r>>1;
    if( left <= mid ) {
        if( !lc[x] ) lc[x] = ++tot;
        update( left,right,v,l,mid,lc[x] );
    }
    if( right > mid ){
        if( !rc[x] ) rc[x] = ++tot;
        update( left,right,v,mid+1,r,rc[x] );
    }
    push_up(x);
}
int merge( int l,int r,int x,int y ){
    if( !x ) return y;
    if( !y ) return x;
    if( l == r ){
        sum[x] += sum[y];
        tree[x] = max( tree[x],tree[y] );
        return x;
    }
    int mid = l+r>>1;
    lc[x] = merge( l,mid,lc[x],lc[y] );
    rc[x] = merge( mid+1,r,rc[x],rc[y] );
    push_up(x);
    return x;
}
int query( int k,int l,int r,int x ){
    if( k > sum[x] ){
        return -1;
    }
    if( l == r ){
        return tree[x];
    }
    int mid =l+r>>1;
    if( sum[ lc[x] ] >= k ){
        return query( k,l,mid,lc[x] );
    }else{
        k -= sum[ lc[x] ];
        return query( k,mid+1,r,rc[x] );
    }
}
int fa[maxn];
void init(int n){
    for( int i = 1;i <= n;i++ ) fa[i] = i;
}
int get( int x ){
    if( x == fa[x] ) return x;
    return fa[x] = get( fa[x] );
}
int val[maxn];
int main(){
    int n,m,x,y,k;
    scanf("%d%d",&n,&m);
    tot = n;
    for( int i = 1;i <= n;i++ ){
        scanf("%d",&val[i]);
        update( val[i],val[i],i,1,n,i );
    }
    init(n);
    for( int i = 0;i < m;i++ ){
        scanf("%d%d",&x,&y);
        x = get(x),y = get(y);
        if( x != y ){
            fa[y] = x;
            merge( 1,n,x,y );
        }
    }
    int q;scanf("%d",&q);
    char str[10];
    for( int i = 0;i < q;i++ ){
        scanf("%s",str);
        if( str[0]=='Q' ){
            scanf("%d%d",&x,&k);
            x = get(x);
                int id;
                id = query(k, 1, n, x);
                printf("%d\n", id);
        }else{
            scanf("%d%d",&x,&y);
            x = get(x),y = get(y);
            if( x != y ){
                fa[y] = x;
                merge( 1,n,x,y );
            }
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值