↓ Skip to main content
  1. Posts/

hdu 3415 Max Sum of Max-K-sub-sequence (单调队列)

·784 words·2 mins
Note: This article is available in Chinese only. 本文暂无英文版本。 View original

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]

代码实现
  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年08月05日 星期五 18时02分36秒
  4File Name :code/hdu/3415.cpp
  5 ************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <stack>
 14#include <set>
 15#include <map>
 16#include <string>
 17#include <cmath>
 18#include <cstdlib>
 19#include <ctime>
 20#define fst first
 21#define sec second
 22#define lson l,m,rt<<1
 23#define rson m+1,r,rt<<1|1
 24#define ms(a,x) memset(a,x,sizeof(a))
 25typedef long long LL;
 26#define pi pair < int ,int >
 27#define MP make_pair
 28
 29using namespace std;
 30const double eps = 1E-8;
 31const int dx4[4]={1,0,0,-1};
 32const int dy4[4]={0,-1,1,0};
 33const int inf = 0x3f3f3f3f;
 34const int N=2E5+7;
 35int a[N],sum[N];
 36int n,k;
 37int on;
 38deque<int>dq;
 39inline bool read(int &num)
 40{
 41    char in;
 42    bool ISN = false;
 43    in=getchar();
 44    if (in==EOF) return false;
 45    while (in!='-'&&(in<'0'||in>'9')) in=getchar();
 46    if (in=='-') ISN = true,num=0;
 47    else num=in-'0';
 48    while (in=getchar(),in>='0'&&in<='9'){
 49	num*=10,num+=in-'0';
 50    }
 51    if (ISN) num=-num;
 52    return true;
 53}
 54int main()
 55{
 56#ifndef  ONLINE_JUDGE
 57    freopen("code/in.txt","r",stdin);
 58#endif
 59
 60    int T;
 61    //scanf("%d",&T);
 62    read(T);
 63    while (T--)
 64    {
 65	scanf("%d%d",&n,&k);
 66//	read(n);
 67//	read(k);
 68	on = n ;
 69	sum[0] = 0 ;
 70	for ( int i = 1 ; i <= n ; i++){
 71	    scanf("%d",&a[i]);
 72	   // read(a[i]);
 73	    a[i+n] = a[i];
 74	}
 75	n = n+k-1;
 76	for ( int i = 1 ; i <= n ; i++) sum[i] = sum[i-1] + a[i];
 77//	for ( int i = 1 ; i <= n ; i++) cout<<a[i]<<" "; cout<<endl;
 78//	for ( int i = 1 ; i <= n ; i++) cout<<sum[i]<<" "; cout<<endl;
 79	dq.clear();
 80	int ans = -inf;
 81	int l,r;
 82	for ( int i = 1 ; i <= n ; i++)  //枚举最后一个元素
 83	{
 84	    while (!dq.empty()&&dq.front()<i-k) dq.pop_front();  //仍然是维护k个,不过由于前缀和的性质,当前要入队的元素是i-1。
 85	    while (!dq.empty()&&sum[dq.back()]>sum[i-1]) dq.pop_back();
 86	    dq.push_back(i-1);
 87	    if (sum[i]-sum[dq.front()]>ans)
 88	    {
 89		ans = sum[i] - sum[dq.front()];
 90		l = dq.front()+1;
 91		r = i ;
 92	    }
 93	}
 94	if (r>on) r%=on;
 95	printf("%d %d %d\n",ans,l,r);
 96    }
 97
 98#ifndef ONLINE_JUDGE
 99    fclose(stdin);
100#endif
101    return 0;
102}

Related

ural 1126. Magnetic Storms (单调队列模板题)

·900 words·2 mins
ural 1126 题意:n个数,求从第k个元素开始,求每k个元素的最大值(一共求n-k+1次) 思路:单调队列。 单调队列学习链接 其实单调队列挺容易的理解的。。。当时觉得写不明白大概是因为看到的代码写得太丑了2333

poj 2823 Sliding Window (单调队列)

·1773 words·4 mins
Sliding Window 看这个问题:An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves rightwards by one position.Your task is to determine the maximum and minimum values in the sliding window at each position. 也就是有一个数列a,要求你求数列b和c,b[i]是a[i]…a[i+w-1]中的最小值,c[i]是最大值。如果a是1,3,-1,-3,5,3,6,7,则b为-1,-3,-3,-3,3,3,c为3,3,5,5,6,7。

hdu 1559 最大子矩阵 (二维前缀和)

·313 words·1 min
hdu 1559 题意:给你一个m×n的整数矩阵,在上面找一个x×y的子矩阵,使子矩阵中所有元素的和最大。 思路:二维前缀和就好。。。和单调栈没有半毛钱关系吧。。。 代码实现 1/* *********************************************** 2Author :111qqz 3Created Time :2016年08月03日 星期三 21时08分18秒 4File Name :code/hdu/1559.cpp 5************************************************ */ 6 7#include <cstdio> 8#include <cstring> 9#include <iostream> 10#include <algorithm> 11#include <vector> 12#include <queue> 13#include <stack> 14#include <set> 15#include <map> 16#include <string> 17#include <cmath> 18#include <cstdlib> 19#include <ctime> 20#define fst first 21#define sec second 22#define lson l,m,rt<<1 23#define rson m+1,r,rt<<1|1 24#define ms(a,x) memset(a,x,sizeof(a)) 25typedef long long LL; 26#define pi pair < int ,int > 27#define MP make_pair 28 29using namespace std; 30const double eps = 1E-8; 31const int dx4[4]={1,0,0,-1}; 32const int dy4[4]={0,-1,1,0}; 33const int inf = 0x3f3f3f3f; 34const int N=1E3+7; 35int a[N][N]; 36int sum[N][N]; 37int n,m,x,y; 38int main() 39{ 40 #ifndef ONLINE_JUDGE 41 freopen("code/in.txt","r",stdin); 42 #endif 43 int T; 44 cin>>T; 45 while (T--) 46 { 47 ms(sum,0); 48 scanf("%d%d%d%d",&n,&m,&x,&y); 49 for ( int i = 1 ; i <= n ; i++) 50 for ( int j = 1 ; j <= m ; j++) 51 { 52 scanf("%d",&a[i][j]); 53 sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1] + a[i][j]; 54 } 55 int ans = 0 ; 56 for ( int i = 1 ; i <= n-x+1 ; i++) 57 for ( int j = 1 ; j <= m-y+1 ; j++) 58 ans = max(ans,sum[i+x-1][j+y-1]-sum[i-1][j+y-1]-sum[i+x-1][j-1]+sum[i-1][j-1]); 59 60 printf("%d\n",ans); 61 } 62 63 #ifndef ONLINE_JUDGE 64 fclose(stdin); 65 #endif 66 return 0; 67}

poj 2796 Feel Good (前缀和,单调栈)

·509 words·2 mins
poj 2796 题意:给出一个人n(1E5)天的情绪值(0..1E6),一段时间的value的定义是这段时间的情绪之和*这段时间情绪的最小值。 现在求value的最大值,并且输出得到这个最大值的区间。