Alexandra has a paper strip with n numbers on it. Let's call them ai from left to right.
Now Alexandra wants to split it into some pieces (possibly 1). For each piece of strip, it must satisfy:
Please help Alexandra to find the minimal number of pieces meeting the condition above.
The first line contains three space-separated integers n, s, l (1 ≤ n ≤ 105, 0 ≤ s ≤ 109, 1 ≤ l ≤ 105).
The second line contains n integers ai separated by spaces ( - 109 ≤ ai ≤ 109).
Output the minimal number of strip pieces.
If there are no ways to split the strip, output -1.
7 2 2 1 3 1 2 4 1 2
3
7 2 2 1 100 1 100 1 100 1
-1
For the first sample, we can split the strip into 3 pieces: [1, 3, 1], [2, 4], [1, 2].
For the second sample, we can't let 1 and 100 be on the same piece, so no solution exists.
求满足上述两个条件情况下m的最小值。即划分区间个数最小
很好的一道DP题,比较综合,把之前学过的单调队列,线段树优化全部都用上了。
定义:Dp[i]为前i个数按题目要求划分的最小段数
Dp[i] = min(Dp[j]) + 1;(其中Dp[j]为满足题意的小于i的j的Dp最小值)
借鉴HDU3530的做法:
http://blog.csdn.net/its_elaine/article/details/72677137
用单调队列按此题的方法维护最大最小值,得到j的区间,
再在线段树中搜索最小dp[j]的值
Status | Accepted |
---|---|
Time | 61ms |
Memory | 6268kB |
Length | 1827 |
Lang | GNU G++ 5.1.0 |
Submitted | 2017-06-12 15:14:35 |
Shared | |
RemoteRunId | 27732877 |
#include
#include
#include
#include
#include
using namespace std;
const int Max = 100005;
const int INF = 0x3f3f3f3f;
struct node{
int l, r;
int val;
}Tr[Max << 2];
int N, S, L;
int A[Max], Qb[Max], Qm[Max];
int Dp[Max];
void getint(int & num){
char c; int flg = 1; num = 0;
while((c = getchar()) < '0' || c > '9') if(c == '-') flg = -1;
while(c >= '0' && c <= '9'){ num = num * 10 + c - 48; c = getchar();}
num *= flg;
}
void build(int i, int l, int r){
Tr[i].l = l, Tr[i].r = r;
Tr[i].val = INF;
if(l == r) return ;
int mid = (l + r) >> 1;
build(i << 1, l, mid);
build(i << 1 | 1, mid + 1, r);
}
void insert(int i, int p, int val){
if(Tr[i].r < p || Tr[i].l > p) return ;
if(p == Tr[i].l && p == Tr[i].r){
Tr[i].val = min(Tr[i].val, val);
return ;
}
insert(i << 1, p, val);
insert(i << 1 | 1, p, val);
Tr[i].val = min(Tr[i << 1].val, Tr[i << 1 | 1].val);
}
int Query(int i, int l, int r){
if(Tr[i].r < l || Tr[i].l > r) return INF;
if(l <= Tr[i].l && r >= Tr[i].r) return Tr[i].val;
return min(Query(i << 1, l, r), Query(i << 1 | 1, l ,r));
}
int main(){
while(~scanf("%d%d%d", &N, &S, &L)){
build(1, 0, N);
insert(1, 0, 0);
for(int i = 1; i <= N; ++ i)
getint(A[i]);
int lstb = 0, lstm = 0;
int frob = 1, from = 1;
int backb = 0, backm = 0;
for(int i = 1; i <= N; ++ i){
while(frob <= backb && A[Qb[backb]] < A[i]) -- backb;
Qb[++ backb] = i;
while(from <= backm && A[Qm[backm]] > A[i]) -- backm;
Qm[++ backm] = i;
while(A[Qb[frob]] - A[Qm[from]] > S){
if(Qb[frob] < Qm[from]) lstb = Qb[frob ++];
else lstm = Qm[from ++];
}
Dp[i] = Query(1, max(lstm, lstb), i - L) + 1;
insert(1, i, Dp[i]);
}
if(Dp[N] >= INF) puts("-1");
else printf("%d\n", Dp[N]);
}
return 0;
}