Comet OJ - Contest #3 (A 比赛 加强版)二分答案

考试的时候同届神犇 JZYshurak 出了一个  n=$10^5$ 的数据加强版. 

刚开始没什么思路,但是忽然想到这个可以转成二分判定+暴力枚举的模型. 

二分 ans, 使得大于等于 ans 的值小于 k 个,这样就能保证只需枚举小于 k 个值了. 

code: 

#include <bits/stdc++.h> 
#define ll long long 
#define N 300002   
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)   
using namespace std;        
int n,k;       
ll A[N];                 
int check(ll tmp) 
{
    int i,j;
    ll re=0;      
    for(i=n;i>=1;--i) 
    {   
        j=lower_bound(A+1,A+1+n,tmp-A[i])-A;   
        if(j<i) 
        {   
            re+=i-j;   
        }    
    }
    return re<1ll*k;        
}
int main() 
{  
    int i,j;  
    setIO("onevsk");  
    scanf("%d%d",&n,&k);  
    for(i=1;i<=n;++i) scanf("%lld",&A[i]);  
    sort(A+1,A+1+n);                
    ll l=1, r=2000000001, mid,ans=0;  
    while(l<=r) 
    {
        // 大于 mid 有 k 个                   
        mid=(l+r)>>1;   
        if(check(mid)) ans=mid, r=mid-1;   
        else l=mid+1;      
    }
    ll re=0;   
    int pp=0;  
    for(i=n;i>=1;--i) 
    {
        for(j=i-1;j>=1;--j) 
        {
            if(A[i]+A[j]<ans) break;       
            re+=A[i]+A[j];   
            ++pp;   
        }
    }                 
    re+=1ll*(1ll*k-1ll*pp)*(ans-1);      
    printf("%lld\n",re);      
    return 0; 
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/11656173.html