题意: 有N个连续的数,求一种划分,使得满足以下条件: 1,每一个块中最少有L个数。2,块中最大数和最小数的差不超过S。求最少要划分成多少块,如果没有满足条件的划分,输出-1;
思路: dp[i]表示前i个字符中满足条件的最小划分。则dp[i]=min(dp[0],dp[1],dp[i-L]),这是第一个条件,我们可以用优先队列简化这个过程。第二个条件需要求在dp[k]+1的位置到dp[i]的位置(k为转移点)这一段中的最大值和最小值的差,这一个过程可以用线段树简化。
/*I have given up the treatment-_-||*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<climits>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<vector>
using namespace std;
#define mod 1000000007
typedef long long LL;
const int maxn=200010;
const int maxm=110;
const int inf=1e9;
int n,m;
LL a[maxn];
struct Node
{
int l;
int r;
LL w;
};
Node Tmax[maxn<<2];
Node Tmin[maxn<<2];
struct Dp
{
LL val;
int pos;
bool operator < (const Dp &tt) const {
return val>tt.val; //val小的在前面
}
}dp[maxn];
void Buildtree(int left,int right,int rt)
{
Tmax[rt].l=Tmin[rt].l=left;
Tmax[rt].r=Tmin[rt].r=right;
if(left==right){
Tmax[rt].w=Tmin[rt].w=a[left];
}
else{
int mid=(left+right)>>1;
Buildtree(left,mid,rt<<1);
Buildtree(mid+1,right,(rt<<1)+1);
Tmax[rt].w=max(Tmax[rt<<1].w,Tmax[(rt<<1)+1].w);
Tmin[rt].w=min(Tmin[rt<<1].w,Tmin[(rt<<1)+1].w);
}
}
LL querymax(int left,int right,int rt)
{
LL temp;
if(Tmax[rt].l>=left&&Tmax[rt].r<=right){
return Tmax[rt].w;
}
else{
temp=-inf;
if(Tmax[rt<<1].r>=left){
temp=max(temp,querymax(left,right,rt<<1));
}
if(Tmax[(rt<<1)+1].l<=right){
temp=max(temp,querymax(left,right,(rt<<1)+1));
}
}
return temp;
}
LL querymin(int left,int right,int rt)
{
LL temp;
if(Tmin[rt].l>=left&&Tmin[rt].r<=right){
return Tmin[rt].w;
}
else{
temp=inf;
if(Tmin[rt<<1].r>=left){
temp=min(temp,querymin(left,right,rt<<1));
}
if(Tmin[(rt<<1)+1].l<=right){
temp=min(temp,querymin(left,right,(rt<<1)+1));
}
}
return temp;
}
int main()
{
#ifndef ONLINE_JUDGE
//freopen ("in.txt" , "r" , stdin);
//freopen ("output.txt" , "w" , stdout);
#endif
int i,j;
int s,l;
scanf("%d%d%d",&n,&s,&l);
for(i=1;i<=n;i++){
scanf("%I64d",&a[i]);
}
Buildtree(1,n,1);
dp[0].val=0;
dp[0].pos=0;
priority_queue<Dp> que;
for(i=1;i<=n;i++){
int temp=i-l;
Dp tp;
if(temp>=0&&dp[temp].val>=0)
que.push(dp[temp]);
while(!que.empty()){
tp=que.top();
int pp=tp.pos;
LL tx=querymax(pp+1,i,1);
LL tn=querymin(pp+1,i,1);
if(abs(tx-a[i])>s||abs(tn-a[i])>s||abs(tx-tn)>s){
que.pop();
continue;
}
else break;
}
if(que.empty()){
dp[i].val=-1;
dp[i].pos=i;
continue;
}
else{
int pp=tp.pos;
dp[i].val=tp.val+1;
dp[i].pos=i;
}
}
printf("%I64d\n",dp[n].val);
return 0;
}