复杂度 .
以 为下标建立 权值线段树,
线段树的每个叶子节点保存 的每个 位置上的 .
则可以直接查询比当前 值 小的,大的,相等的 最大的 , 实现单次转移.
每次 前, 可以被合法转移, 不能被合法转移, 于是在线段树中删除掉其对应的 值.
bug
#include<bits/stdc++.h>
#define reg register
typedef std::pair<int, int> pr;
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 1e6 + 6;
const int inf = 0x3f3f3f3f;
int N;
int L;
int R;
int Lim;
int A[maxn];
int F[maxn];
int sum[maxn];
struct Node{
std::priority_queue <pr> que;
int l, r, max_v;
} T[maxn*4];
void Build(int k, int l, int r){ //
T[k].l = l, T[k].r = r;
if(l == r){ T[k].max_v = -inf; return ; }
int mid = l+r >> 1;
Build(k<<1, l, mid), Build(k<<1|1, mid+1, r);
T[k].max_v = -inf;
}
void Modify(int k, int id){ //
int l = T[k].l, r = T[k].r;
if(l == r){
T[k].que.push(pr(F[id], id));
T[k].max_v = T[k].que.top().first;
return ;
}
int mid = l+r >> 1;
if(sum[id] <= mid) Modify(k<<1, id);
else Modify(k<<1|1, id);
T[k].max_v = std::max(T[k<<1].max_v, T[k<<1|1].max_v);
}
void Del(int k, int id){ //
int l = T[k].l, r = T[k].r;
if(l == r){
while(!T[k].que.empty() && T[k].que.top().second < Lim) T[k].que.pop();
if(T[k].que.empty()) T[k].max_v = -inf;
else T[k].max_v = T[k].que.top().first;
return ;
}
int mid = l+r >> 1;
if(sum[id] <= mid) Del(k<<1, id);
else Del(k<<1|1, id);
T[k].max_v = std::max(T[k<<1].max_v, T[k<<1|1].max_v);
}
int Query(int k, int Ql, int Qr){ //
int l = T[k].l, r = T[k].r;
if(Ql <= l && r <= Qr) return T[k].max_v;
int mid = l+r >> 1;
if(mid+1 <= Ql) return Query(k<<1|1, Ql, Qr);
else if(mid >= Qr) return Query(k<<1, Ql, Qr);
return std::max(Query(k<<1, Ql, Qr), Query(k<<1|1, Ql, Qr));
}
int main(){
freopen("election.in", "r", stdin);
freopen("election.out", "w", stdout);
N = read(), L = read(), R = read();
for(reg int i = 1; i <= N; i ++) A[i] = read(), sum[i] = sum[i-1] + A[i];
for(reg int i = 0; i <= N; i ++) sum[i] += N;
memset(F, -0x3f, sizeof F); F[0] = 0;
Build(1, 0, N<<1); Modify(1, 0);
for(reg int i = L; i <= N; i ++){
Lim = std::max(i-R, 0);
F[i] = std::max(F[i], Query(1, 0, std::max(0, sum[i]-1)) + 1);
F[i] = std::max(F[i], Query(1, sum[i], sum[i]));
F[i] = std::max(F[i], Query(1, std::min(sum[i]+1, N<<1), N<<1) - 1);
if(i-R >= 1) Del(1, i-R);
if(i-L >= 0) Modify(1, i-L);
}
printf("%d
", F[N]);
return 0;
}
/*
Bug List:
1. Build -> push_up
2. For(int i = 1; i <= N; i ++) <<-- For(int i = L; i <= N; i ++)
*/