题意:
有 n 张卡片,每张卡片都有各自的值,值在[0,m]之间,求用这n张卡片能组成最长是多长的顺子
0是一张特殊的卡片,它可以变成[1,m]区间内的任意值
顺子就是包含一串连续的数的序列
先记录哪些牌没有出现过,以及0出现过几次,枚举顺子左端点,二分右端点,二分求得最大的右端点使得在该区间内未出现的数的个数等于0出现的个数
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 10;
int T;
int n,m,x,cnt,sum[maxn];
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) sum[i] = 0;
cnt = 0;
for(int i=1;i<=n;i++) {
scanf("%d",&x);
sum[x] = 1;
if(x==0) cnt++;
}
for(int i=1;i<=m;i++) {
if(sum[i]==0) sum[i] = sum[i-1] + 1;
else sum[i] = sum[i-1];
}
int ans = 0;
for(int i=1;i<=m;i++){
if(ans >= m-i+1) break;
int tem = upper_bound(sum+i, sum+m+1, cnt+sum[i-1])-sum;
ans = max(ans, tem-i);
}
printf("%d\n",ans);
}
return 0;
}