51nod 1153 选择子序列 (好题)
来源:互联网 发布:jq 数组包含 编辑:程序博客网 时间:2024/06/06 02:33
这个题很不错。
采用贪心的思想:首先考虑到在整个序列中取最大值一定是最优的,也就是说B数组的第一个数是A数组的中最大值的下标。而且通过题意我们发现,一旦选定了某个数就把当前的区间划分成两份。比如说第一次选了9,第二次选了10, 那么下一次肯定不会选8(这几个数字说的都是下标),不会垮区间选数,那么我们就可以每次选一个区间最大值,再把区间划分成两份分别查找最大值就可以了。因为每个元素最多访问一遍,再加上线段树找最大值,就是nlong的复杂度了
#include<cstdio>#include<algorithm>using namespace std;typedef long long ll;const int maxn = 1e5;int n;struct p{ ll id, val;}a[maxn * 2];void build(int root, int l, int r){ if(l == r){ scanf("%lld", &a[root].val); a[root].id = l; return; } int mid = (l + r) >> 1; build(root << 1, l, mid); build(root << 1|1, mid + 1, r); if(a[root << 1].val > a[root << 1|1].val){ a[root].val = a[root << 1].val; a[root].id = a[root << 1].id; }else { a[root].val = a[root << 1|1].val; a[root].id = a[root << 1|1].id; }}struct p qu(int root, int l, int r, int s, int t){ p x, y; x.val = y.val = -1e10; if(s <= l && t >= r){ return a[root]; } int mid = (l + r) >> 1; if(s <= mid) x = qu(root << 1, l, mid, s, t); if(t > mid) y = qu(root << 1|1, mid + 1, r, s, t); if(x.val > y.val) return x; return y;}int dfs(int l, int r){ p t; if(l == r) return 1; if(l > r) return 0; t = qu(1, 1, n, l, r); return max(dfs(l, t.id - 1), dfs(t.id + 1, r)) + 1;}int main(){ scanf("%d", &n); build(1, 1, n); printf("%d\n", dfs(1, n)); return 0;}
2017/7/31 更新:
因为这个题目在大佬收录的“o(n)可以过的好题”里面,我就重写了一下,用单调栈代替了线段树。效率提高了一些吧
#include<cstdio>#include<algorithm>#include<stack>using namespace std;typedef long long ll;const int maxn = 1e5;int a[maxn];int left[maxn], right[maxn];int n;stack<int> s;int dfs(int t){ if(t == 0) return 0; if(left[t] == 0 && right[t] == 0) return 1; return max(dfs(left[t]), dfs(right[t])) + 1;}int main(){ int t, pos; scanf("%d", &n); for(int i = 1; i <= n; i++){ scanf("%d", &a[i]); pos = a[i] > t ? i : pos; t = i == 1 ? a[i] : max(a[i], t); while(!s.empty() && a[s.top()] < a[i]){ left[i] = s.top(); s.pop(); } s.push(i); } for(int i = n; i >= 1; i--){ while(!s.empty() && a[s.top()] < a[i]){ right[i] = s.top(); s.pop(); } s.push(i); } printf("%d\n", dfs(pos)); return 0;}
阅读全文
0 0
- 51nod 1153 选择子序列 (好题)
- 选择子序列(51nod-1153)
- 选择子序列 51Nod
- 51nod 1202 子序列个数【dp】好题!
- 51Nod-1153-选择子序列
- 子序列个数 51Nod
- 51nod 1478 括号序列的最长合法子段【思维+前缀和+优先队列】好题!
- 1153 选择子序列
- 51nod 1400 序列分解【Dfs+剪枝】好题~
- 子序列个数(51nod-1202)(dp)
- 51nod 最长公共子序列 (DP+回溯)
- 51nod 1202 子序列个数(DP,递推找规律)
- 51Nod 1006 最长公共子序列Lcs(dp)
- 51nod--1134 最长递增子序列 (动态规划)
- 【51Nod】1006 - 最长公共子序列Lcs(LCS)
- 51nod 1134 最长递增子序列(LIS)
- 51Nod-最长递增子序列(nlogn算法)
- 51nod 1134 最长递增子序列(dp)
- 剑指offer面试题[26]-复杂链表的复制
- 【HDU-1286】找新朋友
- 暂存
- select用法
- 物流管理需求概要图和脑图
- 51nod 1153 选择子序列 (好题)
- HTML笔记-1
- SAML Web SSO如何用浏览器cookie解决跨站点(跨SP)SSO
- 1006 Sum Problem
- 数组的初始化
- 欧拉函数模板题
- git使用
- A+B for Input-Output Practice (VIII)
- 框架和Spring