http://acm.hdu.edu.cn/showproblem.php?pid=3415
题意:求k长度的最大子串和,单调队列
1)STL
原文参考:http://www.cppblog.com/baby-fly/archive/2010/08/04/122213.aspx?Pending=true
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int a[100005],sum[100005];
int main()
{
int T,N,K,max,i,j,x,y;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&K);
deque<int>q1;
sum[0]=0;
for(i=1;i<=N;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
for(i=N+1;i<N+K;i++)
sum[i]=sum[i-1]+a[i-N];
max=-100005;//max=sum[j]-sum[i]
for(j=1;j<N+K;j++)
{
while(!q1.empty()&&sum[j-1]<sum[q1.back()])//找出在1~j之间最小的sum[i]
q1.pop_back();
while(!q1.empty()&&q1.front()<j-K)//删除超过K区间的先前元素
q1.pop_front();
q1.push_back(j-1);
if(sum[j]-sum[q1.front()]>max)
{
max=sum[j]-sum[q1.front()];
x=q1.front()+1;
y=j;
}
}
if(y>N) y=y-N;
printf("%d %d %d\n",max,x,y);
}
return 0;
}
2)
#include <iostream>
#include <cstdio>
using namespace std;
const int NM=200005;
int sum[NM],a[NM],que[NM];
int main()
{
int T,tail,head,i,n,k,mmax,x,y;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
sum[0]=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
for(i=n+1;i<=n+k;i++)
sum[i]=sum[i-1]+a[i-n];
tail=0;head=1;
mmax=-NM;
for(i=1;i<=n+k;i++)
{
while(tail>=head&&sum[i-1]<sum[que[tail]]) //
tail--;
while(tail>=head&&que[head]<i-k) /**/
head++;
tail++;
que[tail]=i-1; //
if(sum[i]-sum[que[head]]>mmax) //
{
mmax=sum[i]-sum[que[head]];
x=que[head]+1;
y=i;
}
}
if(y>n) y-=n;
printf("%d %d %d\n",mmax,x,y);
}
return 0;
}
虽然知道会超时,但另一种思想嘛~~
#include<iostream>
#include<cstdio>#include<queue>
using namespace std;
int a[100005];
int main()
{
int T,N,K,sum,max,i,j,k,x,y;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&K);
for(i=1;i<=N;i++)
scanf("%d",&a[i]);
max=-100005;
for(i=1;i<=N;i++)
{
sum=0;
for(j=i;j<i+K;j++)
{
if(j>N) k=j-N;
else k=j;
sum+=a[k];
if(max<sum)
{max=sum;x=i,y=k;}
}
}
printf("%d %d %d\n",max,x,y);
}
return 0;
}