单调队列优化 单调队列 维护 最大值 队列首元素对应的DP 值 为 dp[low-1] + a[q[front]] 其余元素对应的值(设该元素为q[k]) dp[q[k-1]]+a[q[k]]; Treap 维护下最小值就行了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<iostream>
#include<sstream>
#include<queue>
#include<set>
#include<deque>
#include<iomanip>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
#define lson l , m , rt<<1
#define rson m+1 , r , rt<<1|1
#define keyTree (ch[ch[root][1]][0])
const int maxn = 201111;
const int mask = 32767;
const int INF = (mask << 15) | mask;
int a[maxn], q[maxn], front, rear;
LL sum, dp[maxn], m;
class Treap {
#define L ch[rt][0]
#define R ch[rt][1]
private:
int ch[maxn][2], aux[maxn], sz[maxn];
LL val[maxn];
public:
int tot, rt;
void init() {
sz[0] = 0;
rt = tot = 0;
ch[0][0] = ch[0][1] = 0;
aux[0] = 0;
}
void pushup(int rt) {
sz[rt] = 1 + sz[L] + sz[R];
}
void Rotate(int &rt,int f) {
int t = ch[rt][!f];
ch[rt][!f] = ch[t][f];
ch[t][f] = rt;
pushup(rt);
pushup(t);
rt = t;
}
void insert(int &rt,LL key) {
if(!rt) {
rt=++tot;
val[rt] = key;
L=R=0;
aux[rt] = (rand()<<14);
return;
}
if(key <= val[rt]) {
insert(L,key);
if(aux[L] < aux[rt])
Rotate(rt,1);
}
else {
insert(R,key);
if(aux[R] < aux[rt])
Rotate(rt,0);
}
pushup(rt);
}
void treap_delete(int &rt)
{
if(!L||!R)
rt=L?L:R;
else {
if(aux[L]<aux[R]) {
Rotate(rt,1);
treap_delete(R);
}
else {
Rotate(rt,0);
treap_delete(L);
}
}
}
void del(int &rt,LL key) {
if(key == val[rt]) {
treap_delete(rt);
}
else {
if(key < val[rt])
del(L,key);
else
del(R,key);
sz[rt]--;
}
}
LL getmin(int rt) {
while(L)
rt=L;
return val[rt];
}
}spt;
int main() {
int n, i;
bool flag = false;
scanf("%d%I64d", &n, &m);
for (i = 1; i <= n; ++i)
scanf("%d", a + i), flag |= a[i] > m;
if (flag) {
puts("-1");
return 0;
}
int low = 1;
LL sum = 0;
for (i = 1; i <= n; ++i) {
sum += a[i];
while (low < i && sum > m)
sum -= a[low++];
while (front < rear && a[i] > a[q[rear - 1]]) {
if (front + 1 < rear)
spt.del(spt.rt, dp[q[rear - 2]] + a[q[rear - 1]]);
--rear;
}
q[rear++] = i;
if (front + 1 < rear)
spt.insert(spt.rt, dp[q[rear - 2]] + a[q[rear - 1]]);
while (q[front] < low) {
if (front + 1 < rear)
spt.del(spt.rt, dp[q[front]] + a[q[front + 1]]);
++front;
}
dp[i] = dp[low - 1] + a[q[front]];
if (front + 1 < rear) {
dp[i] = min(dp[i], spt.getmin(spt.rt));
}
}
printf("%I64d\n", dp[n]);
return 0;
}