1551E 题目链接
题意:给出N个数,与一个K,你可以删除一些数,但是删除后该数的右边所有的数都会向左移动一位(区间衔接)。问最少删除多少个数能够使得ai=i的数量大于等于K。或者-1 无解。
解题思路:
对于每个数,计算一下 i-ai 表示位差。然后从小到大排序,当 i-ai的值大于等于0时才开始处理。因为如果为负,代表这个数是不可能移动到ai=i的。
对于 i-ai<= j-aj 如果我们删一些前面的,j位也会左移,所以对后面是没影响的,若删除后面的一些数,对前面则也没有影响。因此只需要对该序列的ai值求一个最长上升子序列即可,操作次数为最小位差(LIS>=K开始更新)
struct pe
{
ll v;
ll id;
} a[22222];
ll b[22222];
bool cmp(pe x,pe y)
{
if(x.v==y.v)
return x.id<y.id;
return x.v<y.v;
}
ll d[3333];
ll cnt=0;
signed main()
{
ll t;
read(t);
while(t--)
{
ll n,k;
read(n);
read(k);
for(int i=1; i<=n; i++)
{
read(b[i]);
a[i].v=i-b[i];
a[i].id=b[i];
}
cnt=0;
ll ans=999999;
sort(a+1,a+1+n,cmp);
ll pos;
for(int i=1; i<=n; i++)
{
if(a[i].v>=0)
{
pos=i;
break;
}
}
for(int i=pos; i<=n; i++)
{
// if(a[i].v)
// printf("%lld ",a[i].v);
if(cnt==0||a[i].id>d[cnt])
{
d[++cnt]=a[i].id;
}
else
{
d[lower_bound(d+1,d+1+cnt,a[i].id)-d]=a[i].id;
}
if(cnt>=k)
{
ans=min(ans,a[i].v);
}
}
if(ans==999999)
{
printf("-1\n");
continue;
}
printf("%lld\n",ans);
}
}