「BalticOI 2010 Day2」 Matching Bins

题意

这个翻译有点小坑,还不如自己看原文。

给定一个长度为 \(N(N\le 2\times 10^4)\) 的整数序列 \(A\),求一个最大的 \(K\),满足前 \(K\) 个数能在接下来 \(K\) 个数中找到一个比他大的数,且每个数能且只能匹配一次。

分析

\(N\) 的范围卡掉了 \(O(N^2\log N)\) 的做法,sort排序光荣去世。

再看这个 \(M(M\le 2\times 10^3)\),小范围加输入提示明显告诉用桶排。

因为总共 \(2K\) 个数,所以从 \(\frac{n}{2}\sim 1\) 枚举 \(K\)

枚举时把左边和右边都排一下序,然后再从 \(1\)\(K\) 比较左边和右边,如果当前右边小于等于左边,直接continue;若没有问题,就输出、return。

最后别忘了 \(K\) 无解的情况,输出一个0。

总时间复杂度 \(O(N^2)\)

Code

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
#define read(x) scanf("%lld",&x)
ll m,n,a[20005],bl[2005],br[2005],l[20005],r[20005];
signed main(){
    read(m),read(n);
    for(ll i=1;i<=n;++i)read(a[i]);
    for(ll i=n/2;i>=1;--i){
        bool vis=0;
        for(ll j=1;j<=i;++j){
            bl[a[j]]++;//左边++
            br[a[j+i]]++;//右边++
        }
        ll la=0,lb=0;
        for(ll j=1;j<=m;++j){
            while(bl[j])--bl[j],l[++la]=j;
            while(br[j])--br[j],r[++lb]=j;
        }//最终还原排序后数组
        for(ll j=1;j<=i;++j){
            if(l[j]>=r[j]){//右边小于等于左边
                vis=1;
                break;
            }
        }
        if(vis==0){
            printf("%lld\n",i);
            return 0;
        }//没问题直接输出
    }
    puts("0");//无解情况
    return 0;
}
posted @ 2024-03-05 21:20  run-away  阅读(19)  评论(0)    收藏  举报