题意:
给定一个序列,问最小能划分成几段,每段元素>=l个并且max-min<=s
题解:
这种一看就是dp[i]表示dp到第i位划分了几段,然后dp[i]=max{dp[j]+1}
考虑这样的max-min是从右向左递增的,所以可以二分
然后得到 j 的左右边界,线段树维护
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 #define inf 2000000001 3 #define maxn 100005 4 using namespace std; 5 int n,s,l; 6 int a[maxn]; 7 struct SegmentTree1 8 { 9 int minv[maxn<<2]; 10 void pushup(int rt) 11 { 12 minv[rt]=min(minv[rt<<1],minv[rt<<1|1]); 13 } 14 void build(int rt,int l,int r) 15 { 16 int mid=(l+r)>>1; 17 minv[rt]=inf; 18 if(l==r)return; 19 build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); 20 pushup(rt); 21 } 22 void update(int rt,int l,int r,int p,int v) 23 { 24 int mid=(l+r)>>1; 25 if(l==r) 26 { 27 minv[rt]=v; 28 return; 29 } 30 if(p<=mid)update(rt<<1,l,mid,p,v); 31 else update(rt<<1|1,mid+1,r,p,v); 32 pushup(rt); 33 } 34 int query(int rt,int l,int r,int ql,int qr) 35 { 36 int ans=inf; 37 if(ql<=l&&r<=qr)return minv[rt]; 38 int mid=(l+r)>>1; 39 if(ql<=mid)ans=min(ans,query(rt<<1,l,mid,ql,qr)); 40 if(qr>mid)ans=min(ans,query(rt<<1|1,mid+1,r,ql,qr)); 41 return ans; 42 } 43 }sgt1; 44 struct SegmentTree2 45 { 46 int maxv[maxn<<2],minv[maxn<<2]; 47 void pushup(int rt) 48 { 49 maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]); 50 minv[rt]=min(minv[rt<<1],minv[rt<<1|1]); 51 } 52 void build(int rt,int l,int r) 53 { 54 int mid=(l+r)>>1; 55 if(l==r) 56 { 57 maxv[rt]=minv[rt]=a[l]; 58 return; 59 } 60 build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); 61 pushup(rt); 62 } 63 int querymin(int rt,int l,int r,int ql,int qr) 64 { 65 int ans=inf; 66 if(ql<=l&&r<=qr)return minv[rt]; 67 int mid=(l+r)>>1; 68 if(ql<=mid)ans=min(ans,querymin(rt<<1,l,mid,ql,qr)); 69 if(qr>mid)ans=min(ans,querymin(rt<<1|1,mid+1,r,ql,qr)); 70 return ans; 71 } 72 int querymax(int rt,int l,int r,int ql,int qr) 73 { 74 int ans=-inf; 75 if(ql<=l&&r<=qr)return maxv[rt]; 76 int mid=(l+r)>>1; 77 if(ql<=mid)ans=max(ans,querymax(rt<<1,l,mid,ql,qr)); 78 if(qr>mid)ans=max(ans,querymax(rt<<1|1,mid+1,r,ql,qr)); 79 return ans; 80 } 81 }sgt2; 82 int dp[maxn]; 83 int get(int l,int r,int x) 84 { 85 int ans=r+1; 86 while(l<=r) 87 { 88 int mid=(l+r)>>1; 89 if(sgt2.querymax(1,1,n,mid+1,x)-sgt2.querymin(1,1,n,mid+1,x)<=s)ans=mid,r=mid-1; 90 else l=mid+1; 91 } 92 return ans; 93 } 94 int main() 95 { 96 scanf("%d%d%d",&n,&s,&l); 97 n++; 98 for(int i=2;i<=n;++i)scanf("%d",&a[i]); 99 a[1]=a[2]; 100 sgt1.build(1,1,n); 101 sgt2.build(1,1,n); 102 sgt1.update(1,1,n,1,0); 103 for(int i=2;i<=n;++i)dp[i]=inf; 104 for(int i=l+1;i<=n;++i) 105 { 106 int R=i-l; 107 int L=get(1,R,i); 108 if(L>R)dp[i]=inf; 109 else dp[i]=sgt1.query(1,1,n,L,R)+1; 110 sgt1.update(1,1,n,i,dp[i]); 111 } 112 if(dp[n]>=inf)dp[n]=-1; 113 printf("%d\n",dp[n]); 114 return 0; 115 }