hdu 3415 Max Sum of Max-K-sub-sequence (单调队列)
hdu 3415 题意:给出n个整数,是一个环(也就是a[n]右边是a[1])求一段长度不超过k的数使得和最大,问最大和是多少并给出这段数的位置。
思路:为了处理环,先把n个数复制一下就好,然后求前缀和sum[i]
由于区间[l,r]的和可以用前缀和表示为sum[r]-sum[l-1]
因此在区间长度小于等于k的前提下,我要求sum[r]-sum[l-1]的最大值,如果我们考虑把端点r固定,那么就是要求[l-1,r-1]中的sum的最小值。
因此我们考虑用单调队列来维护sum[i-k]到sum[i-1]的最小值。
我们的做法是:枚举区间右端点i,同时用单调队列维护i之前的k个数[i-k,i-1]的最小值。
由于要求“If there are more than one result, output the minimum start position, if still more than one , output the minimum length of them.”,因此从后面出队的判断条件是严格的sum[dq.back()]>sum[i-1]
/* ***********************************************
Author :111qqz
Created Time :2016年08月05日 星期五 18时02分36秒
File Name :code/hdu/3415.cpp
************************************************ */
1#include <cstdio>
2#include <cstring>
3#include <iostream>
4#include <algorithm>
5#include <vector>
6#include <queue>
7#include <stack>
8#include <set>
9#include <map>
10#include <string>
11#include <cmath>
12#include <cstdlib>
13#include <ctime>
14#define fst first
15#define sec second
16#define lson l,m,rt<<1
17#define rson m+1,r,rt<<1|1
18#define ms(a,x) memset(a,x,sizeof(a))
19typedef long long LL;
20#define pi pair < int ,int >
21#define MP make_pair
1using namespace std;
2const double eps = 1E-8;
3const int dx4[4]={1,0,0,-1};
4const int dy4[4]={0,-1,1,0};
5const int inf = 0x3f3f3f3f;
6const int N=2E5+7;
7int a[N],sum[N];
8int n,k;
9int on;
10deque<int>dq;
11inline bool read(int &num)
12{
13 char in;
14 bool ISN = false;
15 in=getchar();
16 if (in==EOF) return false;
17 while (in!='-'&&(in<'0'||in>'9')) in=getchar();
18 if (in=='-') ISN = true,num=0;
19 else num=in-'0';
20 while (in=getchar(),in>='0'&&in<='9'){
21 num*=10,num+=in-'0';
22 }
23 if (ISN) num=-num;
24 return true;
25}
26int main()
27{
28#ifndef ONLINE_JUDGE
29 freopen("code/in.txt","r",stdin);
30#endif
1 int T;
2 //scanf("%d",&T);
3 read(T);
4 while (T--)
5 {
6 scanf("%d%d",&n,&k);
7// read(n);
8// read(k);
9 on = n ;
10 sum[0] = 0 ;
11 for ( int i = 1 ; i <= n ; i++){
12 scanf("%d",&a[i]);
13 // read(a[i]);
14 a[i+n] = a[i];
15 }
16 n = n+k-1;
17 for ( int i = 1 ; i <= n ; i++) sum[i] = sum[i-1] + a[i];
18// for ( int i = 1 ; i <= n ; i++) cout<<a[i]<<" "; cout<<endl;
19// for ( int i = 1 ; i <= n ; i++) cout<<sum[i]<<" "; cout<<endl;
20 dq.clear();
21 int ans = -inf;
22 int l,r;
23 for ( int i = 1 ; i <= n ; i++) //枚举最后一个元素
24 {
25 while (!dq.empty()&&dq.front()<i-k) dq.pop_front(); //仍然是维护k个,不过由于前缀和的性质,当前要入队的元素是i-1。
26 while (!dq.empty()&&sum[dq.back()]>sum[i-1]) dq.pop_back();
27 dq.push_back(i-1);
28 if (sum[i]-sum[dq.front()]>ans)
29 {
30 ans = sum[i] - sum[dq.front()];
31 l = dq.front()+1;
32 r = i ;
33 }
34 }
35 if (r>on) r%=on;
36 printf("%d %d %d\n",ans,l,r);
37 }
1#ifndef ONLINE_JUDGE
2 fclose(stdin);
3#endif
4 return 0;
5}