• poj2985


    树状数组求第k大值

    思路有一点想ST表

    将求第k大变为求第(tot-k+1)小的数,tr[i]统计小于等于i的数的总数

    每次不断逼近,若当前[ans,ans+(1<<i)]在范围内,则加上,否则直接到下一次循环

    过程中的一个地方要注意(详见代码注释)

    #include<cstdio>
    #include<cctype>
    using namespace std;
    int n,m,fa[200002],tr[200002],siz[200002];
    
    inline void read(int &x){
        char ch=getchar();x=0;
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    } 
    
    inline int findfa(int x){
        if(fa[x]==x)return x;return fa[x]=findfa(fa[x]);
    }
    
    inline void updata(int now,int ad){
        for(;now<=n;now+=now&-now)tr[now]+=ad;
    }
    
    inline int query(int k){
        int cnt=0,ans=0;
        for(int i=20;i>=0;i--){
            ans+=1<<i;
            if(ans>n||cnt+tr[ans]>=k)ans-=1<<i;else cnt+=tr[ans];//这里if语句中一定的是<=,否则若存在多个与k大数相同的数就会存在漏洞
        }
        return ans+1;
    }
    
    int main(){
        read(n);read(m);
        int tot=n;
        for(int i=1;i<=n;i++){siz[i]=1;fa[i]=i;}
        updata(1,n);
        while(m--){
            int c,x,y;
            read(c);
            switch(c){
                case 0:{
                    read(x);read(y);int fx=findfa(x),fy=findfa(y);
                    if(fx==fy)continue;
                    updata(siz[fx],-1);updata(siz[fy],-1);
                    siz[fy]+=siz[fx];updata(siz[fy],1);fa[fx]=fy;tot--;   
                    break;} 
                case 1:read(x);printf("%d\n",query(tot-x+1));break;
            }
        }
    }
  • 相关阅读:
    ACL最大权限及相关命令
    ACL权限设置
    Linux权限管理--ACL权限简介
    Linux用户信息文件/etc/passwd
    本地光盘yum源的搭建
    响应式 和 移动 web
    svg
    vi 命令
    html 语法
    运营给的广告设计稿如何做
  • 原文地址:https://www.cnblogs.com/MikuKnight/p/8974079.html
Copyright © 2020-2023  润新知