Codeforces Round #271 (Div. 2) E. Pillars(线段树优化DP)
来源:互联网 发布:mysql 5.7.17.tar.gz 编辑:程序博客网 时间:2024/06/05 15:48
题目链接:点击打开链接
题意:一个n个数的序列,每个数有一个高度值h[i]。 求一个最长子序列,要求相邻两个数满足| h[i] - h[i-1] | >= d。 并要求打印出该序列。
类似于最长上升子序列, DP思想很简单, 但是可惜n太大了, 二重循环会超时。 所以要想办法优化掉第二层循环。
观察发现, 第二层所做的事情就是在所有满足j<i && | h[i] - h[j] | >= d 的j中找到最大的d[j]。
j < i很容易满足, 按照顺序加入就可以了, 但是还要满足大小关系, 怎么办呢?
把不等式变形就成了: h[j] <= h[i] - d 或者 h[j] >= h[i] + d 。 这不就是一个区间吗? 所以我们可以以高度为区间建一棵线段树,由于h[i]太大,先离散化一下。
可见, 线段树的区间下标并不是没有用的, 适当利用, 也可以用来维护一些信息。
细节参见代码:
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<stack>#include<bitset>#include<cstdlib>#include<cmath>#include<set>#include<list>#include<deque>#include<map>#include<queue>#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;typedef long long ll;const double PI = acos(-1.0);const double eps = 1e-6;const int mod = 1000000000 + 7;const int INF = 1000000000;const int maxn = 100000 + 10;int T,m,dd,n,d[maxn],pre[maxn];ll a[maxn],b[maxn];struct node { int v, id;}maxv[maxn<<2];void PushUp(int o) { if(maxv[o<<1].v <= maxv[o<<1|1].v) maxv[o] = maxv[o<<1|1]; else maxv[o] = maxv[o<<1];}void build(int l, int r, int o) { int m = (l + r) >> 1; maxv[o].v = 0; if(l == r) return ; build(l, m, o<<1); build(m+1, r, o<<1|1);}void update(int L, int R, int v, int l, int r, int o) { int m = (l + r) >> 1; if(L <= l && r <= R) { if(maxv[o].v < d[v]) { maxv[o].v = d[v]; maxv[o].id = v; } return ; } if(L <= m) update(L, R, v, l, m, o<<1); if(m < R) update(L, R, v, m+1, r, o<<1|1); PushUp(o);}node query(int L, int R, int l, int r, int o) { int m = (l + r) >> 1; if(L <= l && r <= R) { return maxv[o]; } node ans ; ans.v = 0; if(L <= m) { node v = query(L, R, l, m, o<<1); if(ans.v < v.v) ans = v; } if(m < R) { node v = query(L, R, m+1, r, o<<1|1); if(ans.v < v.v) ans = v; } PushUp(o); return ans;}void print(int root) { if(d[root] == 0) return ; else print(pre[root]); if(pre[root] == 0) printf("%d",root); else printf(" %d",root);}int main() { scanf("%d%d",&n,&dd); for(int i=1;i<=n;i++) { scanf("%I64d",&a[i]); b[i] = a[i]; } sort(b+1, b+1+n); int m = unique(b+1, b+1+n) - b - 1; d[1] = 0; build(1, m, 1); int ans = 0, root = -1; for(int i=1;i<=n;i++) { d[i] = 0; int L = upper_bound(b+1, b+1+m, a[i] - dd) - b; int R = lower_bound(b+1, b+1+m, a[i] + dd) - b; L--; if(L >= 1) { node cur = query(1, L, 1, m, 1); if(cur.v + 1 > d[i]) { d[i] = cur.v + 1; pre[i] = cur.id; } } if(R <= m) { node cur = query(R, m, 1, m, 1); if(cur.v + 1 > d[i]) { d[i] = cur.v + 1; pre[i] = cur.id; } } int v = lower_bound(b+1, b+1+m, a[i]) - b; update(v, v, i, 1, m, 1); if(ans < d[i]) { ans = d[i] ; root = i; } } if(ans == 0) { printf("0\n"); return 0; } printf("%d\n",ans); print(root); printf("\n"); return 0;}
0 0
- Codeforces Round #271 (Div. 2) E Pillars(dp+线段树优化)
- Codeforces Round #271 (Div. 2) E. Pillars(线段树优化DP)
- Codeforces Round #271 (Div. 2)E. Pillars(dp+线段树优化)
- Codeforces Round #271 (Div. 2) E题 Pillars(线段树维护DP)
- Codeforces Round #271 (Div. 2) E. Pillars(线段树+DP)
- Codeforces Round #271 (Div. 2) E. Pillars
- codeforces 474E Pillars(线段树+dp)
- Codeforces 474E Pillars dp+线段树
- Codeforces 474E Pillars dp+线段树
- Codeforces Round #271 (Div. 2)——E. Pillars
- E. Pillars(Codeforces Round #271)
- 【Codeforces Round 271 (Div 2)E】【离散化线段树】Pillars 最长连续序列使得序列相邻的数差值至少为k
- Codeforces Round #353 (Div. 2) E 线段树+dp
- Codeforces 474E Pillars dp+线段树(水
- Codeforces Round #353 (Div. 2) E. Trains and Statistic (线段树+dp)
- Codeforces Round #450 (Div. 2) E. Maximum Questions(线段树+DP)
- Codeforces Round #271 (Div. 2) E 离散化+线段树
- Codeforces Round #353 (Div. 2) E. Trains and Statistic dp 贪心,DP,线段树
- 数据库修改过表或字段后,更新dbml
- Android设计模式源码解析之外观模式(Facade)
- java特种兵读书笔记(5-1)——并发之基础介绍
- IE6下margin双倍边距Bug的处理办法
- android L SystemProperties属性解析
- Codeforces Round #271 (Div. 2) E. Pillars(线段树优化DP)
- 图形处理(八)点云重建(上)点云滤波、尖锐特征边增采样、移除离群点
- React Native 入门环境搭建
- Android程序混淆代码
- 基于jQuery下拉两级联动select
- Mysql中创建根据第二个自增的id
- OCruntime交换方法用在处理iOS版本跨度问题的解决
- 图形处理(九)点云重建(下)法矢求取、有向距离场等值面提取
- HashMap的工作原理总结