mirror of
https://github.com/Kiritow/OJ-Problems-Source.git
synced 2024-03-22 13:11:29 +08:00
Create 3017.cpp
This commit is contained in:
parent
d9f30124cc
commit
3b18366ca6
62
POJ/3017.cpp
Normal file
62
POJ/3017.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
#define MAXN 1000100
|
||||
#define INF 0x3f3f3f3f
|
||||
|
||||
long long a[MAXN];
|
||||
long long dp[MAXN];
|
||||
|
||||
long long t[MAXN];
|
||||
int tbegin,tend;
|
||||
|
||||
int main()
|
||||
{
|
||||
int N;
|
||||
long long M;
|
||||
scanf("%d %I64d",&N,&M);
|
||||
tbegin=tend=0;
|
||||
long long blocksum=0;
|
||||
int blockbegin=0;
|
||||
for(int i=1;i<=N;i++)
|
||||
{
|
||||
scanf("%I64d",&a[i]);
|
||||
///如果整个数列中任何一个数超过M,那么是无论如何都不能划分的(没有负数存在)
|
||||
if(a[i]>M)
|
||||
{
|
||||
printf("-1\n");
|
||||
return 0;
|
||||
}
|
||||
blocksum+=a[i];
|
||||
while(blocksum>M)
|
||||
{
|
||||
///如果现在假设的连续区块 ID: blockbegin, blockbegin+1 ... i
|
||||
///求和超过M,那么这是一个非法区块,需要减去最左端的区块(向右收缩)
|
||||
blockbegin++;///【疑问】为什么blockbegin要在前面?
|
||||
blocksum-=a[blockbegin];
|
||||
}
|
||||
///队列用于维护每个区块中最大的值的ID
|
||||
while(tbegin<tend&&a[t[tend-1]]<=a[i]) tend--;
|
||||
t[tend++]=i;
|
||||
///队列中最左端的值的ID在blockbegin的左端,弹出
|
||||
while(tbegin<tend&&t[tbegin]<=blockbegin) tbegin++;
|
||||
|
||||
///未进行DP前初始化为INF
|
||||
dp[i]=INF;
|
||||
|
||||
int maxvalbegin=blockbegin;
|
||||
|
||||
for(int index=tbegin;index<tend;index++)
|
||||
{
|
||||
long long tmp=dp[maxvalbegin]+a[t[index]];
|
||||
dp[i]=min(dp[i],tmp);
|
||||
maxvalbegin=t[index];
|
||||
}
|
||||
}
|
||||
printf("%I64d\n",dp[N]);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user