codeforces 487B

题意:

给定一个序列,问最小能划分成几段,每段元素>=l个并且max-min<=s

题解:

这种一看就是dp[i]表示dp到第i位划分了几段,然后dp[i]=max{dp[j]+1}

考虑这样的max-min是从右向左递增的,所以可以二分

然后得到 j 的左右边界,线段树维护

  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
",dp[n]);
114     return 0;
115 }
View Code
原文地址:https://www.cnblogs.com/uuzlove/p/10448020.html