博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Codeforces 488D Strip (set+DP)
阅读量:6614 次
发布时间:2019-06-24

本文共 5528 字,大约阅读时间需要 18 分钟。

D. 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.

Sample test(s)
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.

 

 

 

 

 题意是给出一个长度为n的序列,问最少能够分割多少分。

 使得,每一分的长度大于等于l,最大值与最少值的差值最大为s 。

 我的方法是3颗线段树,2颗维护最大最小值, 1棵维护 dp[i-1]+1 最小的位置。 

 然后二分出尽量左的位置使得最大最小值差值最大不超过s ,

 然后从这个位置到当前位置取出 dp[i-1]+1 最小的位置。然后再更新。

 

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;typedef long long LL;const int N = 100010;const int inf = 1e9+7;const double PI = acos(-1.0);const double eps = 1e-6 ;#define root 1,n,1#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define lr rt<<1#define rr rt<<1|1int n , m , dif , e[N] , dp[N]; int d_M[N<<2] , d_m[N<<2] , p_m[N<<2];void Up( int rt ) { d_M[rt] = max( d_M[lr] , d_M[rr] ); d_m[rt] = min( d_m[lr] , d_m[rr] );}void Up2( int rt ) { if( dp[ p_m[lr] - 1 ] + 1 < dp[ p_m[rr] - 1 ] + 1 ) p_m[rt] = p_m[lr] ; else p_m[rt] = p_m[rr] ;}void build( int l , int r , int rt ){ if( l == r ) { p_m[rt] = l ; d_M[rt] = d_m[rt] = e[l] ; return ; } int mid = (l+r)>>1; build(lson) , build(rson) ; Up(rt); Up2(rt);}int temp_M , temp_m , temp_dpm;void update( int l , int r , int rt , int x , int val ) { if( l == r ) { dp[ x ] = val ; return ; } int mid = (l+r)>>1 ; if( x <= mid ) update( lson , x , val ); else update(rson,x,val); Up2(rt);}int get_min_pos( int l , int r , int rt , int L , int R ){ if( l == L && r == R ) { return p_m[rt]; } int mid = (l+r) >> 1 ; if( R <= mid ) return get_min_pos( lson , L ,R ) ; else if( L > mid ) return get_min_pos( rson ,L ,R ) ; else { int temp_l = get_min_pos( lson , L , mid ) , temp_r = get_min_pos( rson , mid+1 , R ); if( dp[ temp_l - 1 ] + 1 < dp[ temp_r - 1 ] + 1 ) return temp_l; else return temp_r; }}void query( int l , int r , int rt , int L , int R ) { if( l == L && r == R ) { temp_M = max( temp_M , d_M[rt] ) ; temp_m = min( temp_m , d_m[rt] ); return ; } int mid = ( l+r ) >>1; if( R <= mid ) query(lson,L,R); else if( L > mid )query(rson,L,R); else query(lson,L,mid) , query(rson,mid+1,R);}void init() { for( int i = 1 ; i <= n ; ++i ) dp[i] = inf ;}void clr() { temp_m = inf , temp_M = -inf; temp_dpm = inf ; }int find( int l , int r ){ int pos = -1 , goal = r ; while( l <= r ) { int mid = (l+r)>>1; clr(),query(root,mid,goal); if( abs( temp_M - temp_m ) <= dif ) pos = mid , r = mid - 1; else l = mid + 1; } return pos;}void test() { for( int i = 0 ; i <= n ; ++i ) cout << dp[i] << ' ' ;cout << endl ;}void run () { for( int i = 1 ; i <= n ; ++i ) cin >> e[i] ; init(),build(root); for( int i = 1 ; i <= n ; ++i ) { int pos = find( 1 , i ) ; if( pos == -1 || i - pos + 1 < m ) continue ; if( pos - 1 == i - m ) { update( root , i , dp[ pos - 1 ] + 1 ) ; continue ; } pos = get_min_pos( root , pos , i - m ); update( root , i , dp[ pos - 1 ] + 1 ) ; } if( dp[n] < inf )cout << dp[n] << endl ; else cout << "-1" << endl ;}int main(){ #ifdef LOCAL freopen("in.txt","r",stdin); #endif // LOCAL ios::sync_with_stdio(false); while( cin >> n >> dif >> m )run() ;}
View Code

 

之前一直不会set...

在cf上看别人的代码,被完爆码量。

 

 

begin() 返回指向第一个元素的迭代器
clear() 清除所有元素
count() 返回某个值元素的个数
empty() 如果集合为空,返回true(真)
end() 返回指向最后一个元素之后的迭代器,不是最后一个元素
equal_range() 返回集合中与给定值相等的上下限的两个迭代器
erase() 删除集合中的元素
find() 返回一个指向被查找到元素的迭代器
get_allocator() 返回集合的分配器
insert() 在集合中插入元素
lower_bound() 返回指向大于(或等于)某值的第一个元素的迭代器
key_comp() 返回一个用于元素间值比较的函数
max_size() 返回集合能容纳的元素的最大限值
rbegin() 返回指向集合中最后一个元素的反向迭代器
rend() 返回指向集合中第一个元素的反向迭代器
size() 集合中元素的数目
swap() 交换两个集合变量
upper_bound() 返回大于某个值元素的迭代器
value_comp() 返回一个用于比较元素间的值的函数
 
 
用两个set。
一个维护区间范围。
一个维护dp[i-1]+1最小。
set的好处是可以按照给出值查找并删除那个元素。
就相当于有两棵现成的红黑树,替代了线段树的功能了。
 

 

#include 
#define X first#define Y second#define INF 1000000009using namespace std;typedef pair
pii;int n, s, l, a[100005];int dp[100005];set
S, R;int main(){ scanf("%d %d %d", &n, &s, &l); for(int i = 1; i <= n; i ++) scanf("%d", &a[i]); memset(dp, 0, sizeof dp); int j = 1; for(int i = 1; i <= n; i ++){ S.insert(pii(a[i], i)); while(!S.empty() && S.rbegin()->X - S.begin()->X > s){ S.erase(pii(a[j], j)); j ++; } if(i >= l && dp[i - l] != -1) R.insert(pii(dp[i - l], i - l)); while(!R.empty() && R.begin()->Y < j - 1) R.erase(R.begin()); if(R.empty()) dp[i] = -1; else dp[i] = R.begin()->X + 1; } printf("%d\n", dp[n]); return 0;}
View Code

 

转载于:https://www.cnblogs.com/hlmark/p/4126954.html

你可能感兴趣的文章
js的自执行函数
查看>>
移植Qt与Tslib到X210开发板的体会
查看>>
Nginx + webpy 和FastCGI搭建webpy环境
查看>>
new static 跟 new self 区别
查看>>
PLSQL Develope连接oracle数据库配置
查看>>
Jmeter测试带加密参数的接口
查看>>
使用JdbcTemplate过程中使用到多个参数和like模糊
查看>>
解决eclipse中无法删除Tomcat服务器中的项目,报maven is required and cannot be removed from the server错误情况...
查看>>
修改页面JS 360浏览器
查看>>
尚学linux课程---3、linux网络说明
查看>>
Git 跟 GitHub 是什么关系?
查看>>
String.split()方法
查看>>
IE6下jQuery选中select的BUG
查看>>
Tensorflow在win10下的安装(CPU版本)
查看>>
嵌入式平台做深度学习算法,不可不重视的4件事
查看>>
一次优化记录
查看>>
如何调用一个数据完整的firefox浏览器
查看>>
cgroup代码浅析(2)
查看>>
会计的思考(42):会计如何转变为公司的内部财务顾问
查看>>
利用钥匙串,在应用里保存用户密码的方法
查看>>