洛谷P4197 Peaks 线段树合并

在这里插入图片描述

考虑离线 然后 从权值小的开始建边 进行线段树合并

#include<iostream>
#include<algorithm>

using namespace std;

const int N = (5e5 + 10) * 4;
typedef pair<int,int> PII;

int h[N];
int n,m,q,fa[N];

struct node{
    
    
    int x,y,w,type,id;
    bool operator < (const node &p)const{
    
    
        if(w == p.w) return type < p.type;
        return w < p.w;
    }
}edge[N];

int T[N];

struct ns{
    
    
    int l,r,v;
}tree[N];
int ans;
int insert(int p,int l,int r,int val){
    
    
    if(!p) p = ++ans;
    tree[p].v++;
    if(l < r){
    
    
        int mid = l + r >> 1;
        if(mid >= val) tree[p].l = insert(tree[p].l,l,mid,val);
        if(mid < val) tree[p].r = insert(tree[p].r,mid + 1,r,val);
    }
    return p;
}

int merge(int x,int y,int l,int r){
    
    
    if(!x) return y;
    if(!y) return x;
    if(!tree[x].l && !tree[x].r){
    
    
        tree[x].v += tree[y].v;
        return x;
    }
    int mid = l + r >> 1;
    tree[x].l = merge(tree[x].l,tree[y].l,l,mid);
    tree[x].r = merge(tree[x].r,tree[y].r,mid + 1,r);
    tree[x].v = tree[tree[x].l].v + tree[tree[x].r].v;
    return x;
}

int query(int x,int l,int r,int v){
    
    
    if(l == r){
    
    
        return l;
    }
    int mid = l + r >> 1;
    if(tree[tree[x].l].v >= v) return query(tree[x].l,l,mid,v);
    else return query(tree[x].r,mid + 1,r,v - tree[tree[x].l].v);
}

int get(int x){
    
    
    if(fa[x] == x) return x;
    return fa[x] = get(fa[x]);
}

int a[N];
int output[N];
void build(){
    
    
    for(int i = 1; i <= n; i++){
    
    
        T[i] = insert(T[i],1,n,h[i]);
    }
    for(int i = 1; i <= m + q; i++){
    
    
        if(edge[i].type == 0){
    
    
            int x = get(edge[i].x),y = get(edge[i].y);
            if(x != y){
    
    
                T[y] = merge(T[y],T[x],1,n);
                fa[x] = y;
            }
        }else{
    
    
            int x = get(edge[i].x);
            if(tree[T[x]].v < edge[i].y) output[edge[i].id] = -1;
            else output[edge[i].id] = a[query(T[x],1,n,tree[T[x]].v - edge[i].y + 1)];
        }
    }
}

int main(){
    
    
    cin >> n >> m >> q;
    for(int i = 1; i <= n; i++) cin >> h[i],a[i] = h[i];
    for(int i = 1; i <= n; i++) fa[i] = i;

    sort(a + 1,a + n + 1);
    for(int i = 1; i <= n; i++) h[i] = lower_bound(a + 1,a +n + 1,h[i]) - a;

    for(int i = 1; i <= m; i++){
    
    
        scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].w),edge[i].type = 0;;
    }

    for(int i = 1; i <= q; i++){
    
    
        scanf("%d%d%d",&edge[m + i].x,&edge[m + i].w,&edge[m + i].y),edge[m + i].type = 1;
        edge[m + i].id = i;
    }

    sort(edge + 1,edge + m + q + 1);

    build();

    for(int i = 1; i <= q; i++) cout << output[i] << endl;



    return 0;
}

猜你喜欢

转载自blog.csdn.net/qqqingyi/article/details/120277188
今日推荐