[CF 474E] Pillars (线段树+dp)
题目链接:http://codeforces.com/contest/474/problem/F
意思是给你两个数n和d,下面给你n座山的高度。
一个人任意选择一座山作为起始点,向右跳,但是只能跳到高度差的绝对值大于等于d的山上。
问跳过的最长路径是什么。
设dp[h[i]]是跳到第i座山的最长路径长度。
那么dp[h[i]] = max( dp[h[j]] ) + 1 ( |h[i]-h[j]| >=d && i>j )
因为要查询区间最大值,所以考虑用线段树实现。
从左向右扫,线段树seg[i]维护的是走到高度为i的山走的最长路径
那么先找出 区间 [0,h[i]-d] 的最长路径,再找出区间 [h[i]+d,n]的最长路径
然后求出最大的加1,再放入线段树的h[i]位置中。
注意要维护路径 还有离散化
#include <bits/stdc++.h>
using namespace std;
typedef long long LL; const int MAX_N = *1e5+;
LL h[MAX_N],b[MAX_N];
// 这里写的时候偷懒了,sum代表高度对应的最长路径,maxn代表当前高度对应的最近的下标
int sum[MAX_N<<], maxn[MAX_N<<],dp[MAX_N],qq[MAX_N],n,d;
int route[MAX_N]; void push_up(int idx){
sum[idx] = max(sum[idx<<],sum[idx<<|]);
if( sum[idx<<]>sum[idx<<|] ) maxn[idx] = maxn[idx<<];
else maxn[idx] = maxn[idx<<|];
} // 更新pos的山的路径长,并且下标置为i
void update(int pos,int x,int i,int idx,int l,int r){
if( l==r ){
sum[idx] = x;
maxn[idx] = i;
return;
}
int m = l+r>>;
if( pos<=m ) update(pos,x,i,idx<<,l,m);
else update(pos,x,i,idx<<|,m+,r);
push_up(idx);
} // 传入的i是要被修改的,返回路径最长的山的位置
int query(int L,int R,int &i,int idx,int l,int r){
if( R<l||r<L ) {
i = -;
return -;
}
if( L<=l&&R>=r ) {
i = maxn[idx];
return sum[idx];
}
int m = l+r>> , res = -;
if( L<=m ) {
int s;
int Q = query(L,R,s,idx<<,l,m);
if( Q>res ){
i = s;
res = Q;
}
}
if( R>m ){
int s;
int Q = query(L,R,s,idx<<|,m+,r);
if( Q>res ) {
res = Q;
i = s;
}
}
return res;
} int main(){
memset(maxn,-,sizeof(maxn)); int ptr = ;
scanf("%d%d",&n,&d);
for(int i=;i<n;i++){
scanf("%I64d",&h[i]);
b[ptr++] = h[i];
b[ptr++] = h[i]-1LL*d;
b[ptr++] = h[i]+1LL*d;
}
sort(b,b+ptr);
int ub = unique(b,b+ptr) - b; for(int i=;i<n;i++){
int r = lower_bound(b,b+ub,h[i]+d) - b;
int lmax = -;
int rs = query(r,ptr-,lmax,,,ptr-);
int rmax = -;
int l = lower_bound(b,b+ub,h[i]-d) - b;
int ls = query(,l,rmax,,,ptr-);
qq[i] = max(ls,rs);
int t = lower_bound(b,b+ub,h[i]) - b;
update(t,qq[i]+,i,,,ptr-);
if(ls>rs){
dp[i] = rmax;
} else {
dp[i] = lmax;
}
}
int idx = maxn[];
int ED = sum[];
printf("%d\n",ED);
int ptrr = ;
route[ptrr++] = idx;
while( route[ptrr-]> ){
int s = route[ptrr-];
route[ptrr] = dp[s];
ptrr++;
}
while( route[ptrr-]< ) ptrr--;
for(int i=ptrr-;i>=;i--){
printf("%d ",route[i]+);
}
return ;
}
代码
[CF 474E] Pillars (线段树+dp)的更多相关文章
- Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)
[题目链接] http://www.tsinsen.com/A1219 [题意] 给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u- ...
- HDU 3016 Man Down (线段树+dp)
HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- CodeForces–833B--The Bakery(线段树&&DP)
B. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...
- lightoj1085 线段树+dp
//Accepted 7552 KB 844 ms //dp[i]=sum(dp[j])+1 j<i && a[j]<a[i] //可以用线段树求所用小于a[i]的dp[j ...
- HDU-3872 Dragon Ball 线段树+DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3872 题意:有n个龙珠按顺序放在一列,每个龙珠有一个type和一个权值,要求你把这n个龙珠分成k个段, ...
- HDU4521+线段树+dp
题意:在一个序列中找出最长的某个序列.找出的序列满足题中的条件. 关键:对于 第 i 个位置上的数,要知道与之相隔至少d的位置上的数的大小.可以利用线段树进行统计,查询.更新的时候利用dp的思想. / ...
- Codeforces Round #343 (Div. 2) D - Babaei and Birthday Cake 线段树+DP
题意:做蛋糕,给出N个半径,和高的圆柱,要求后面的体积比前面大的可以堆在前一个的上面,求最大的体积和. 思路:首先离散化蛋糕体积,以蛋糕数量建树建树,每个节点维护最大值,也就是假如节点i放在最上层情况 ...
- [Codeforces Round #296 div2 D] Clique Problem 【线段树+DP】
题目链接:CF - R296 - d2 - D 题目大意 一个特殊的图,一些数轴上的点,每个点有一个坐标 X,有一个权值 W,两点 (i, j) 之间有边当且仅当 |Xi - Xj| >= Wi ...
- Special Subsequence(离散化线段树+dp)
Special Subsequence Time Limit: 5 Seconds Memory Limit: 32768 KB There a sequence S with n inte ...
随机推荐
- ORACLE 事务学习
以下内容为本人的学习手记,有不足和理解错误的地方,请谨慎参考. 在ORACLE中的事务并不像MSSQL中的事务那样可以随意控制. ORACLE的事务是在进行数据第一次被修改后自动开启的无法显示的开启事 ...
- html简介
什么是 HTML? HTML 是用来描述网页的一种语言. HTML 指的是超文本标记语言 (Hyper Text Markup Language) HTML 不是一种编程语言,而是一种标记语言 (ma ...
- Entity Framework菜鸟初飞
Entity Framework菜鸟初飞 http://blog.csdn.net/zezhi821/article/details/7235134
- (转)textarea去掉右侧滚动条,去掉右下角拖拽
本文转载自:http://blog.csdn.net/cctv_end/article/details/7946188 代码: <TEXTAREA style= "overflo ...
- 51nod 1348 乘积之和
用(r-l+2)维向量f[l,r]表示区间[l,r]内选i个数(0<=i<=r-l+1)相乘的所有方案之和,可以发现f[l,r]=f[l,m]*f[m+1,r],题目模数100003较小, ...
- windows类书的学习心得(转载)
原文网址:http://www.blogjava.net/sound/archive/2008/08/21/40499.html 现在的计算机图书发展的可真快,很久没去书店,昨日去了一下,真是感叹万千 ...
- SVN分支的合并和同步
使用svn几年了,一直对分支和合并敬而远之,一来是因为分支的管理不该我操心,二来即使涉及到分支的管理,也不敢贸然使用合并功能,生怕合并出了问题对团队造成不良影响,最主要的原因是,自己对分支的目的和合并 ...
- ios8 ios7 tableview cell 分割线左对齐
ios8中左对齐代码 //加入如下代码 -(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cel ...
- 黄聪:C#超级延时方法,延迟系统时间但系统又能同时能执行其它任务
private void Delay(int Millisecond) //延迟系统时间,但系统又能同时能执行其它任务: { DateTime current = DateTime.Now; whil ...
- room_speed和image_speed
room_speed是游戏步数,每秒多少步(步事件)image_speed是动画帧率room_speed变则整个游戏变慢image_speed变只是该object动画变慢 除了游戏全局加速减速,一般不 ...