Codeforces Round #278 (Div. 1) B
来源:互联网 发布:杜兰特软蛋知乎 编辑:程序博客网 时间:2024/06/12 09:10
B. Strip
题意:n个数,需要把他们切割成尽量少的部分,每部分连续,长度至少为l,其中最大数与最小数的差不能超过s。
思路:首先,预处理每个区间内的最大数和最小数(spare table),然后就可以用dp的方法解决这个问题。dp的时候,利用预处理,对每个位置i找到以i为结尾,最左边能在哪个地方切割(二分查找,位置记为j),所以以i结尾合法的切割范围就是j~i-l。如果在位置k切割,状态转移就是dp(i)=dp(k)+1。我们要做的就是从j~i-l转移到i,这个过程需要用线段树优化,不然会T。。
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespace std; const int maxn=100010; const int INF=1e9+10; int a[maxn]; int MIN[maxn][20]; int MAX[maxn][20]; int dp[maxn]; int getmin(int l,int r){ int d=r-l+1; int k=-1; while(d){ k++; d>>=1; } return min(MIN[l][k],MIN[r-(1<<k)+1][k]); } int getmax(int l,int r){ int d=r-l+1; int k=-1; while(d){ k++; d>>=1; } return max(MAX[l][k],MAX[r-(1<<k)+1][k]); } struct node{ int l,r; int val; }tree[maxn<<2]; void build_tree(int n,int l,int r){ tree[n].l=l; tree[n].r=r; tree[n].val=INF; if(l==r)return; int mid=(l+r)>>1; build_tree(n<<1,l,mid); build_tree((n<<1)|1,mid+1,r); } inline void push_up(int n){ tree[n].val=min(tree[n<<1].val,tree[(n<<1)|1].val); } void update(int n,int pos,int v){ if(tree[n].l==tree[n].r){ tree[n].val=v; return; } int mid=(tree[n].l+tree[n].r)>>1; if(pos<=mid) update(n<<1,pos,v); else update((n<<1)|1,pos,v); push_up(n); } int query(int n,int l,int r){ if(tree[n].l==l&&tree[n].r==r){ return tree[n].val; } int mid=(tree[n].l+tree[n].r)>>1; if(r<=mid){ return query(n<<1,l,r); }else{ if(l>mid){ return query((n<<1)|1,l,r); }else{ return min( query(n<<1,l,mid) , query((n<<1)|1,mid+1,r) ); } } } int main(){ int n,s,L; cin>>n>>s>>L; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); MAX[i][0]=MIN[i][0]=a[i]; } int tmp=1; int k=0; while(tmp<n){ tmp<<=1; k++; } for(int j=1;j<=k;j++){ for(int i=1;i+(1<<j)-1<=n;i++){ MIN[i][j]=min(MIN[i][j-1],MIN[i+(1<<(j-1)) ][j-1]); MAX[i][j]=max(MAX[i][j-1],MAX[i+(1<<(j-1)) ][j-1]); } } for(int i=1;i<=n;i++)dp[i]=INF; build_tree(1,0,n); update(1,0,0); for(int i=1;i<=n;i++){ int l=0,r=i-L; int pos=-1; while(l<=r){ int mid=(l+r)>>1; if(getmax(mid+1,i)-getmin(mid+1,i)<=s){ pos=mid; r=mid-1; }else{ l=mid+1; } } if(pos!=-1&&pos<=i-L){ int t=query(1,pos,i-L); if(t>=INF)continue; dp[i]=t+1; update(1,i,dp[i]); } } if(dp[n]>=INF) cout<<-1<<endl; else cout<<dp[n]<<endl; return 0; }
0 0
- Codeforces Round #278 (Div. 1) B
- Codeforces Round #278 (Div. 1) B. Strip
- Codeforces Round #278 (Div. 1) 解题报告 A.B.
- Codeforces Round #278 (Div. 1) B. Strip(Dp+multiset维护)
- Codeforces Round #278 (Div. 2) A B
- Codeforces Round #278 (Div. 2) A, B
- Codeforces Round #278 (Div. 2) B
- Codeforces Round #131 (Div. 1) B. Numbers
- Codeforces Round #119 (Div. 1) B. AlgoRace
- Codeforces Round #215 (Div. 1) <A-B>
- Codeforces Round #225 (Div. 1) B. Volcanoes
- Codeforces Round #230 (Div. 1)B,C
- Codeforces Round #239 (Div. 1)(A,B)
- Codeforces Round #253 (Div. 1)-A,B
- Codeforces Round #254 (Div. 1)-A,B
- Codeforces Round #240 (Div. 1)B
- Codeforces Round #259 (Div. 1) B题
- Codeforces Round #268 (Div. 1) B
- MFC学习笔记之八————颜色对话框与字体对话框
- ListView滚动到底部自动加载更多
- poj1797 Heavy Transportation(最短路变形)
- Model Training and Tuning
- vc6.0 中getline需要按两次回车的解决方法
- Codeforces Round #278 (Div. 1) B
- 用java对密码进行MD5加密
- python 装饰器与AOP
- Mysql碰到“Every derived table must have its own alias”类似错误说明
- 互联网协议入门(二)
- 捕捉尝试登陆失败的用户信息
- 《字符串和多维数组》的思维导图
- Reading files in MySQL with file_priv = no
- test