Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 10129 Accepted Submission(s): 3729 Problem Description Given a circle sequence A[1],A[2],A[3]......A[n]. Circle sequence means the left neighbour of A[1] is A[n] , and the right neighbour of A[n] is A[1].
Input The first line of the input contains an integer T(1<=T<=100) which means the number of test cases.
Output For each test case, you should output a line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the minimum start position, if still more than one , output the minimum length of them.
Sample Input 4 6 3 6 -1 2 -6 5 -5 6 4 6 -1 2 -6 5 -5 6 3 -1 2 -6 5 -5 6 6 6 -1 -1 -1 -1 -1 -1
Sample Output 7 1 3 7 1 3 7 6 2 -1 1 1
Author shǎ崽@HDU
Source HDOJ Monthly Contest – 2010.06.05
Recommend lcy
|
题目大意:现在给你N个数,问你这N个数组成的循环中,最大的序列,这个序列的长度不大于K,要求输出序列的最大值,起点和终点,
思路:这个题目的话,首先要吧这个环弄成线形的,就是用后面的k个值代表前面的,但是这个题目的话,我们要求的是前缀和,这样我们就能用单调队列来维护这个东西的不下降,并且要限制K个元素
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=100000*2+10;
const int inf=1e9;
int a[maxn];
int q[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(a,0,sizeof(a));
memset(q,0,sizeof(q));
int n,k;
scanf("%d%d",&n,&k);
a[0]=0;
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
a[i]+=a[i-1];
}
for(int i=n; i<n+k; i++)
a[i]=a[n]+a[i-n];
/*for(int i=1;i<n+k;i++)
cout<<a[i]-a[i-1]<<" ";
cout<<endl;
for(int i=1;i<n+k;i++)
cout<<a[i]<<" ";*/
int head=0,tail=0;
int maxx=-inf;
int l,r;
for(int i=1;i<n+k;i++)
{
while(head<tail&&a[i-1]<a[q[tail-1]])
tail--;
q[tail++]=i-1;
while(head<tail&&i-q[head]>k)
head++;
if(maxx<a[i]-a[q[head]])
{
maxx=a[i]-a[q[head]];
l=q[head]+1;
r=i>n?i%n:i;
}
}
printf("%d %d %d\n",maxx,l,r);
}
}