hdu 3415 Max Sum of Max-K-sub-sequence 解题报告 单调队列
解题思路:单调队列处理就行了。注意对sum[0]的处理。
#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<map>
#include<stack>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<fstream>
#include<iomanip>
#pragma warning(disable:4996)
#define INF 0x3f3f3f3f
#define ll long long
#define PI acos(-1.0)
const int N = 1000010;
const int maxn = 1e9;
using namespace std;
int a[100005];
int sum[200010];//因为是circle,所以要开两倍大小
int main()
{
int t, n, k;
scanf("%d", &t);
deque<int> Q;
while (t--)
{
scanf("%d%d", &n, &k);
memset(a, 0, sizeof(a));
memset(sum, 0, sizeof(sum));
Q.clear();
int ans = -INF;
int s, e;//标记开始和结尾
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
sum[i] = sum[i - 1] + a[i];//记录前缀和
}
for (int i = n + 1; i <= n + k - 1; i++)
{
sum[i] = sum[i - 1] + a[i - n];
}
for (int i = 0; i < n + k - 1; i++)
{
while (!Q.empty() && sum[i] < sum[Q.back()])//保证单调性,确保后加进来的前缀和大于等于前一个前缀和
{
Q.pop_back();
}
while (!Q.empty() && Q.front() < i - k+1)//保证区间长度不超过k
{
Q.pop_front();
}
Q.push_back(i);
if (sum[i+1] - sum[Q.front()] > ans)
{
ans = sum[i+1] - sum[Q.front()];
s = Q.front() + 1;
e = i+1;
}
}
if (e > n)//如果circle了,要减去n得到下标
e -= n;
printf("%d %d %d\n", ans, s, e);
}
}