Codeforces Round #734 (Div. 3) E Fixed Points (思维)

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);

    }



}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值