CF1692E题解
__vector__ · · 题解
题目翻译
给你一个
在一次操作中,你可以删掉第一个元素或最后的元素。
求使得剩下元素总和等于
思路
考虑到只能在首尾删元素,可以将问题转化为:
在数列
暴力思路
显然可以暴力枚举每一个区间,前缀和
复杂度
优化
首先设数列第
枚举左端点的部分不太好优化,那就优化选择右端点的部分。
显然,固定了左端点
而前缀和数组是升序的!
也就是说可以用 lower_bound,
但是要注意,lower_bound 求出来的右端点
算出
这道题就做完了。
复杂度
代码:
#include <bits/stdc++.h>
using namespace std;
namespace Main
{
const int maxn=2e5+5;
int t,n,s;
int a[maxn];
int qzh[maxn];//前缀和
int len[maxn];
//len[i] 代表第 i 个元素开始有多少个相邻的相同元素
void main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&s);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
qzh[i]=qzh[i-1]+a[i];
}
for(int i=n;i>=1;i--)
{
if(i==n)
{
len[i]=1;
continue;
}
if(a[i]==a[i+1])len[i]=len[i+1]+1;
else len[i]=1;
}
if(qzh[n]<s)
{
printf("-1\n");
continue;
}
int maxlen=0;
for(int l=1;l<=n;l++)
{
int r=lower_bound(qzh+l,qzh+n+1,s+qzh[l-1])-qzh;
if(a[r+1]==0&&r<n)r=r+1+len[r+1]-1;
if(r==n+1)
{
continue;
}
maxlen=max(maxlen,r-l+1);
}
printf("%d\n",n-maxlen);
}
}
}
int main()
{
Main::main();
return 0;
}