「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;
}

浙公网安备 33010602011771号