Strip
time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

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:

  • Each piece should contain at least l numbers.
  • The difference between the maximal and the minimal number on the piece should be at most s.

Please help Alexandra to find the minimal number of pieces meeting the condition above.

Input

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

Output the minimal number of strip pieces.

If there are no ways to split the strip, output -1.

Examples
input
7 2 2
1 3 1 2 4 1 2
output
3
input
7 2 2
1 100 1 100 1 100 1
output
-1
Note

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.

【题意】给你一个序列,让你分成若干份,对于每一份,要求最大值-最小值<=s,且每一份长度不小于L。求分得的最小份数,若不可分,输出-1.

【分析】考虑DP,dp[i]代表1~i分得的最小份数,则dp[i]=min(dp[j])+1,j当然得满足条件,首先i-j+1>=L,然后max[j,i]-min[j,i]<=s,考虑到区间最大值-最小值具有单调性,所以二分极限的j,然后判断一下j的可行性,可由j-1~i-L之间的最小dp值转移过来。区间最大最小值用RMQ,线段树维护区间dp最小值。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e5+;;
const int M = ;
const int mod = 1e9+;
const double pi= acos(-1.0);
typedef pair<int,int>pii;
int n,len,s;
int dp[N];
int a[N],mi[N*];
int mn[N][],mx[N][],mm[N];
void init() {
for(int j=; j<=mm[n]; ++j) {
for(int i=; i+(<<j)-<=n; ++i) {
mn[i][j]=min(mn[i][j-],mn[i+(<<(j-))][j-]);
mx[i][j]=max(mx[i][j-],mx[i+(<<(j-))][j-]);
}
}
}
int getmx(int l,int r) {
int k = mm[r-l+];
return max(mx[l][k],mx[r-(<<k)+][k]);
}
int getmn(int l,int r) {
int k = mm[r-l+];
return min(mn[l][k],mn[r-(<<k)+][k]);
}
void upd(int l,int r,int rt,int pos){
if(l==r){
mi[rt]=dp[l];
return;
}
int mid=(l+r)>>;
if(pos<=mid)upd(l,mid,rt<<,pos);
else upd(mid+,r,rt<<|,pos);
mi[rt]=min(mi[rt<<],mi[rt<<|]);
}
int qry(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
return mi[rt];
}
int ret=inf,mid=(l+r)>>;
if(L<=mid)ret=min(ret,qry(L,R,l,mid,rt<<));
if(R>mid)ret=min(ret,qry(L,R,mid+,r,rt<<|));
return ret;
}
void solve(int pos){
int l=,r=pos,ans=-;
while(l<=r){
int mid=(l+r)>>;
int minn=getmn(mid,pos);
int maxn=getmx(mid,pos);
if(maxn-minn<=s)r=mid-,ans=mid;
else l=mid+;
}
if(ans==-||pos-ans+<len)dp[pos]=inf;
else if(ans==)dp[pos]=;
else dp[pos]=qry(max(ans-,),pos-len,,n,)+;
}
int main(){
mm[]=-;
for(int i=; i<N; ++i)mm[i]=(i&(i-))?mm[i-]:mm[i-]+;
scanf("%d%d%d",&n,&s,&len);
for(int i=;i<=n;i++)scanf("%d",&a[i]),mn[i][]=mx[i][]=a[i];
init();
met(dp,inf);
for(int i=;i<=n;i++){
if(i<len)dp[i]=inf;
else solve(i);
upd(,n,,i);
}
if(dp[n]>=inf)puts("-1");
else printf("%d\n",dp[n]);
return ;
}

Codeforces Round #278 (Div. 1) Strip (线段树 二分 RMQ DP)的更多相关文章

  1. Codeforces Round #530 (Div. 2) F 线段树 + 树形dp(自下往上)

    https://codeforces.com/contest/1099/problem/F 题意 一颗n个节点的树上,每个点都有\(x[i]\)个饼干,然后在i节点上吃一个饼干的时间是\(t[i]\) ...

  2. Codeforces Round #426 (Div. 2) D 线段树优化dp

    D. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...

  3. Please, another Queries on Array?(Codeforces Round #538 (Div. 2)F+线段树+欧拉函数+bitset)

    题目链接 传送门 题面 思路 设\(x=\prod\limits_{i=l}^{r}a_i\)=\(\prod\limits_{i=1}^{n}p_i^{c_i}\) 由欧拉函数是积性函数得: \[ ...

  4. Nastya Hasn't Written a Legend(Codeforces Round #546 (Div. 2)E+线段树)

    题目链接 传送门 题面 题意 给你一个\(a\)数组和一个\(k\)数组,进行\(q\)次操作,操作分为两种: 将\(a_i\)增加\(x\),此时如果\(a_{i+1}<a_i+k_i\),那 ...

  5. Codeforces Round #422 (Div. 2) E. Liar 后缀数组+RMQ+DP

    E. Liar     The first semester ended. You know, after the end of the first semester the holidays beg ...

  6. Codeforces Round #267 (Div. 2) C. George and Job(DP)补题

    Codeforces Round #267 (Div. 2) C. George and Job题目链接请点击~ The new ITone 6 has been released recently ...

  7. Codeforces Round #278 (Div. 1) B. Strip multiset维护DP

    B. Strip Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/487/problem/B De ...

  8. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  9. Codeforces Round #278 (Div. 2) D. Strip 线段树优化dp

    D. Strip time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...

随机推荐

  1. Java程序运行时的几个区域

    Java运行时涉及到的区域 几个基本概念: 1.Java对象     2.Java方法    3.一个编译好的类,以class文件的形式出现 4.Java的本地方法   5.线程私有和线程共有   一 ...

  2. 【bzoj3362-导航难题】带权并查集

    题意: 约翰所在的乡村可以看做一个二维平面,其中有N 座牧场,每座牧场都有自己的坐标,编号为1到N.牧场间存在一些道路,每条道路道路连接两个不同的牧场,方向必定平行于X 轴或Y轴.连通两座牧场之间的路 ...

  3. 【vijos】P1659 河蟹王国

    [算法]线段树 [题解]区间加上同一个数+区间查询最大值.注意和谐值可以是负数,初始化ans为负无穷大. #include<cstdio> #include<algorithm> ...

  4. 4、什么是事务?MySQL如何支持事务?

    什么是事务? 事务是由一步或几步数据库操作序列组成逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行.程序和事务是两个不同的概念.一般而言:一段程序中可能包含多个事务.(说白了就是几步的数据库操作 ...

  5. HDU 2199 二分

    我们可以发现这个函数是单增的,那么这样二分就好了. 反思:刚转C++,不会用scanf读入实数.(scanf("%lf",&y)) //By BLADEVIL #inclu ...

  6. Linux中查看进程占用内存的情况【转】

    转自:http://hutaow.com/blog/2014/08/28/display-process-memory-in-linux/ Linux中查看某个进程占用内存的情况,执行如下命令即可,将 ...

  7. nodejs 使用redis 管理session

    一.在开发机安装redis并远程连接 因本人的远程开发机配置原因,使用jumbo安装redis 首先登录开发机,并使用jumbo 安装redis:jumbo install redis 查看redis ...

  8. C基础 内存统一入口

    引言  - malloc 引述 C标准中堆上内存入口就只有 malloc, calloc, realloc . 内存回收口是 free. 常见的一种写法是 struct person * per = ...

  9. Java将CST的时间字符串转换成需要的日期格式字符串

    已知得到的Date类型的变量meettingdate 的值为Sun Dec 16 10:56:34 CST :现在要将它改为yyyy-MM-dd类型或yyyy年MM月dd日: 变为yyyy年MM月dd ...

  10. Leetcode 之Evaluate Reverse Polish Notation(41)

    很简单的一道题,定义一个栈保留操作数,遇操作符则弹出运算即可. bool isOperator(string &op) { //注意用法 && string("+-* ...