• BZOJ 3545 peaks (离线版&&在线版)


    离线版

    首先将询问和加边一起排个序

    对每个节点建一棵主席树,连边时主席树合并即可

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 1000010;
    
    int n,m,q;
    int a[maxn],b[maxn],fa[maxn],rt[maxn],ans[maxn],p,tot;
    struct Node{
        int sz,ls,rs;
    }t[maxn<<2];
    struct Q{
        int a,b,c,ok,id;
    }c[maxn<<2];
    
    int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); }
    
    bool cmp(Q a,Q b){
        if(a.c==b.c) return a.ok<b.ok; // 询问和添加一起排序,并且保证询问前添加已全部完成 
        return a.c<b.c;
    }
    
    void modify(int &i,int l,int r,int p){
        if(!i) i=++tot; // 如果原来存在主席树节点就用原来的 
        t[i].sz=1;
        if(l==r) return;
        int mid=(l+r)/2;
        if(p<=mid) modify(t[i].ls,l,mid,p);
        else modify(t[i].rs,mid+1,r,p);
    }
    
    int query(int i,int l,int r,int k){
        if(l==r) return l;
        int sum=t[t[i].ls].sz;
        int mid=(l+r)/2;
        if(k<=sum) return query(t[i].ls,l,mid,k);
        else return query(t[i].rs,mid+1,r,k-sum);
    }
    
    int merge(int u,int v){ // 线段树合并 
        if(!u||!v) return u|v;
        else if(!t[u].ls&&!t[u].rs){
            t[u].sz+=t[v].sz;
            return u;
        }else{
            t[u].ls=merge(t[u].ls,t[v].ls);
            t[u].rs=merge(t[u].rs,t[v].rs);
            t[u].sz=t[u].sz+t[v].sz;
            return u;
        }
    }
    
    ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f;}
    
    int main(){
        n=read(),m=read(),q=read();
        for(int i=1;i<=n;i++) a[i]=read(),b[i]=a[i],fa[i]=i;
        sort(b+1,b+1+n);
        p=unique(b+1,b+1+n)-b-1;
        for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+p,a[i])-b;
        for(int i=1;i<=m;i++) c[i].a=read(),c[i].b=read(),c[i].c=read(),c[i].ok=0;
        for(int i=m+1;i<=m+q;i++) c[i].a=read(),c[i].c=read(),c[i].b=read(),c[i].ok=1,c[i].id=i-m;
        
        sort(c+1,c+1+m+q,cmp);
        
        for(int i=1;i<=n;i++) modify(rt[i],1,p,a[i]);
    
        for(int i=1;i<=m+q;i++){
            if(c[i].ok==0){
                int u=find(c[i].a),v=find(c[i].b);
                if(u!=v){
                    fa[u]=v;
                    rt[v]=merge(rt[u],rt[v]);
                }
            }else{
                int u=find(c[i].a);
                if(t[rt[u]].sz<c[i].b) ans[c[i].id]=-1;
                else ans[c[i].id]=b[query(rt[u],1,p,t[rt[u]].sz-c[i].b+1)]; // 第 k 大 
            }
        }
        
        for(int i=1;i<=q;i++){ printf("%d\n",ans[i]); }
    
        return 0;
    }
  • 相关阅读:
    OpenStack对象存储管理手册(5) OpenStack对象存储系统管理3
    hdu1568Fibonacci
    智能手机中显示信号强度格数
    上篇日本人经营之道 一破坏对手的情绪乱其方寸
    基于Wince的计算器程序
    shell 字符串操作
    轻松记住大端小端的含义
    如何把手机变成你的救生设备
    PM是一个事实
    mysql 5.6 online ddl 测试
  • 原文地址:https://www.cnblogs.com/tuchen/p/10390309.html
Copyright © 2020-2023  润新知