• HDU 6231 K-th Number


    HDU 6231 K-th Number

    题目大意:

    给一个序列A,将其所有的大于等于K长度的子区间中,第K大的数取出来,放到B数组中。求B数组中第M大的数。

    思路:

    将所有的区间都取出来显然不行,时间复杂度爆炸。维护起来更奇怪。

    可以考虑二分答案——先二分出这个B数组中第M大的数x,然后判断行不行——是否在原来的序列A中,有>=M个子区间,其>=x的数至少有K个。

    我们知道这里是有单调性的——如果x增大,那么>=x的数至少有K个的区间数目就会变少;否则会增大。

    接下来的问题是如何求出>=x的数至少有K个的子区间数目。

    我们采用两个指针(l,r)的方法。不停地移动右指针,直到>=x的数有K个之后,移动左指针,直到左指针正好到从它原先位置开始的第一个>=x的数的位置上时——我们可以计算这特定K个数的贡献(具体请见代码qwq)

    #include<bits/stdc++.h>
    #define MAXN 100010
    #define ll long long
    using namespace std;
    int n,T,maxx,cnt,cnt2;
    ll sum;
    int a[MAXN],prime[MAXN],cur[MAXN],not_prime[MAXN],Prime[MAXN];
    inline void pre_solve(){
    	not_prime[1]=1;
    	for(int i=2;i<=100000;i++){
    		if(not_prime[i]==0){
    			prime[++cnt]=i;
    		}
    		for(int j=1;j<=cnt&&prime[j]*i<=100000;j++){
    			not_prime[prime[j]*i]=1;
    			if(i%prime[j]==0) break;
    		}
    	}
    }
    inline int ll calc(ll x){
        ll cur_ans=0;
        memcpy(cur,a,sizeof(int)*(n+1));
        for(int i=1;i<=n;i++) cur[i]%=x;
        sort(&cur[1],&cur[n+1]);
        int l=1,r=n;
        while(l<r){
            while(cur[l]%x==0) l++;
            while(cur[r]%x==0) r--;
            int cur_sum=cur[l]%x;
            cur_ans+=cur_sum;
            while((cur[r]+cur_sum)>x){
                cur_sum-=x-cur[r];
                r--;
            }
            cur[r]+=cur_sum;
            l++;
        }
        return cur_ans;
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&T);
        pre_solve();
        while(T--){
            sum=0,maxx=0,cnt2=0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                sum+=a[i];
                maxx=max(maxx,a[i]);
            }
            long long ans=sum-maxx;
            int pre=2;
            for(int i=pre;i<=(int)sqrt(sum);i++){
                if(not_prime[i]==true||sum%i!=0) continue;
                else{
                    Prime[++cnt2]=i;
                    pre=i;
                    while(sum%i==0) sum/=i;
                }
            }
            // for(int i=1;i<=cnt2;i++) printf("%d ",Prime[i]); puts("");
            for(int i=1;i<=cnt2;i++){
                ans=min(ans,calc(Prime[i]));
            }
            if(sum!=1) ans=min(ans,calc(sum));
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    python 文件操作
    高级函数
    运行cadence dpi例子出现的问题
    我对验证的一些理解【zz】
    archlinux 下挂载ntfs分区,显示"permission denied"
    vs2012安装SharePoint 2013的项目模版
    Iptables工具的使用
    webmin简介
    cassandra简介
    linux中端口扫描
  • 原文地址:https://www.cnblogs.com/fengxunling/p/13667892.html
Copyright © 2020-2023  润新知