可以尺取吗?//先看代码上一行
尺取,双指针:我先限定 l = 1;让 r 向后走,走到 r - l + 1 正好为 题目所给的 n 在这个过程中,我们判断我们所需要的答案,之后让 l 后移 1 位,用循环吧a【l】小于等于 0 的给删掉;
删完后在判断这个是否是我们需要的答案,重复此过程,直至遍历完整个数组。
这个的分析感觉一点错都没有,先是TLE,之后又是WA,找不到哪里有问题。
#include<iostream>
using namespace std;
const int N=1e6+5;
int a[N],ans[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int m,n;
scanf("%d%d",&m,&n);
for(int i=1;i<=m;i++)
{
scanf("%d",&a[i]);
ans[i]=ans[i-1]+a[i];
}
for(int i=1;i<n;i++)
ans[i+m]=ans[m+i-1]+a[i];
int sum=ans[1],ml=1,mr=1;
for(int l=1,r=1;l<m||r<n+m-1;)//1 2 3 位置应该是合理即可,顺序都可以
{
while(a[l]<=0&&l<r) l++;// 1
if(sum<ans[r]-ans[l-1])
{
ml=l;mr=r;
sum=ans[r]-ans[l-1];
}
while(r-l<n&&r<m+n-1)// 2
{
r++;
if(sum<ans[r]-ans[l-1])
{
ml=l;mr=r;
sum=ans[r]-ans[l-1];
}
}
if(l<m) l++;// 3
}
printf("%d %d %d\n",sum,ml,mr-mr/(m+1)*m);
}
return 0;
}
单调队列//双端队列
维护一个递增的队列(对于每一个 i ,队列都是不一样的),我们取寻找当前 i 之前最小的前缀和
;可能还是有点蒙,我们需要取找每一个 i 值所对应的那个最小值(当前 子序列的和 是当前 i 与之前的差 及sum【i】-sum【q . front()】),前面比 i 大的在之前已经找过,无需在多考虑。先敲一下,进行理解
在看看HDU1003
#include<iostream>
#include<deque>
using namespace std;
const int N=1e6+5;
int a[N],sum[N];
int main()
{
ios::sync_with_stdio(0);
int T;
cin>>T;
while(T--)
{
int m,n,x;
cin>>m>>n;a[0]=0;
for(int i=1;i<=m;i++)
{
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
for(int i=1;i<=n;i++)
sum[i+m]=sum[m+i-1]+a[i];
deque<int>q;
int ans=-1000000010,ml=1,mr=1;
for(int i=1;i<=m+n;i++)
{
while(q.size()&&sum[i-1]<sum[q.back()])
q.pop_back();
while(q.size()&&i-q.front()>n)
q.pop_front();
q.push_back(i-1);
if(ans<sum[i]-sum[q.front()])
{
ans=sum[i]-sum[q.front()];
ml=q.front()+1;
mr=i;
}
}
cout<<ans<<' '<<ml<<' '<<mr-mr/(m+1)*m<<'\n';
}
return 0;
}