鏈接: http://acm.hdu.edu.cn/showproblem.php?pid=3415
意甲冠軍:環(huán)。要找出當(dāng)中9長(zhǎng)度小于等于K的和最大的子段。
思路:不能採(cǎi)用最暴力的枚舉。題目的數(shù)據(jù)量是10^5,O(N^2)的枚舉回去超時(shí)。本題採(cǎi)用的非常巧妙的DP做法,是用單調(diào)隊(duì)列優(yōu)化的DP。
運(yùn)用的是STL的deque,從i:1~a找到以當(dāng)中以i為尾的符合條件的子段。并將i本身放入雙向隊(duì)列。全部i從隊(duì)列后放入,保證了隊(duì)列的單調(diào)性。
代碼:
#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; }
版權(quán)聲明:本文博客原創(chuàng)文章,博客,未經(jīng)同意,不得轉(zhuǎn)載。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
