您的位置:首页 > 产品设计 > UI/UE

HDU 3415 Max Sum of Max-K-sub-sequence 最长K子段和

2015-07-03 13:07 519 查看
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3415

意甲冠军:环。要找出当中9长度小于等于K的和最大的子段。

思路:不能採用最暴力的枚举。题目的数据量是10^5,O(N^2)的枚举回去超时。本题採用的非常巧妙的DP做法,是用单调队列优化的DP。

运用的是STL的deque,从i:1~a找到以当中以i为尾的符合条件的子段。并将i本身放入双向队列。全部i从队列后放入,保证了队列的单调性。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <ctype.h>
#include <algorithm>
#include <string>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define maxn 100005*2
#define maxm
#define INF 0x7fffffff
typedef long long ll;
using namespace std;
int num[maxn],sum[maxn];
int main()
{
int tot;
scanf("%d",&tot);
while(tot--)
{
int a,b;
scanf("%d%d",&a,&b);
scanf("%d",&num[1]);
sum[1]=num[1];
for(int i=2;i<=a;i++)
{
scanf("%d",&num[i]);
sum[i]=sum[i-1]+num[i];
}
for(int i=a+1;i<a+b;i++)
sum[i]=sum[i-1]+num[i-a];
deque < int > dd;
int ans=-INF,head=-1,tail=-1;
for(int i=1;i<a+b;i++)
{
while(!dd.empty()&&sum[i-1]<sum[dd.back()])
dd.pop_back();
while(!dd.empty()&&i>dd.front()+b)
dd.pop_front();
dd.push_back(i-1);
if(sum[i]-sum[dd.front()]>ans)
{
ans=sum[i]-sum[dd.front()];
head=dd.front()+1;
tail=i;
}
}
if(head>a)
head-=a;
if(tail>a)
tail-=a;
printf("%d %d %d\n",ans,head,tail);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: