hdu 1025 Constructing Roads In JGShining's Kingdom(最长上升子序列(LIS)O(nlogn)算法)
2013-05-17 18:26
295 查看
这一题很容易抽象成最长上升子序列问题:
最长上升子序列问题:
给出一个由n个数组成的序列x[1..n],找出它的最长单调上升子序列。即求最大的m和a1,
a2……,am,使得a1<a2<……<am且x[a1]<x[a2]<……<x[am]。
动态规划求解思路分析:(O(n^2))
经典的O(n^2)的动态规划算法,设A[i]表示序列中的第i个数,F[i]表示从1到i这一段中以i结尾的最长上升子序列的长度,初始时设F[i] = 0(i = 1, 2, ..., len(A))。则有动态规划方程:F[i] = max{1, F[j] + 1} (j = 1, 2, ..., i - 1, 且A[j] < A[i])。
贪心+二分查找:(O(nlogn))
开辟一个栈,每次取栈顶元素s和读到的元素a做比较,如果a>s, 则加入栈;如果a<s,则二分查找栈中的比a大的第1个数,并替换。 最后序列长度为栈的长度。
这也是很好理解的,对x和y,如果x<y且E[y]<E[x],用E[x]替换 E[y],此时的最长序列长度没有改变但序列Q的''潜力''增大。
举例:原序列为1,5,8,3,6,7
栈为1,5,8,此时读到3,则用3替换5,得到栈中元素为1,3,8, 再读6,用6替换8,得到1,3,6,再读7,得到最终栈为1,3,6,7 ,最长递增子序列为长度4。
用贪心+二分的方法很容易模拟出来,需要注意的就是二分的写法,而且需要输出最长上升子序列时,直接输出栈中的元素就行了。
最长上升子序列问题:
给出一个由n个数组成的序列x[1..n],找出它的最长单调上升子序列。即求最大的m和a1,
a2……,am,使得a1<a2<……<am且x[a1]<x[a2]<……<x[am]。
动态规划求解思路分析:(O(n^2))
经典的O(n^2)的动态规划算法,设A[i]表示序列中的第i个数,F[i]表示从1到i这一段中以i结尾的最长上升子序列的长度,初始时设F[i] = 0(i = 1, 2, ..., len(A))。则有动态规划方程:F[i] = max{1, F[j] + 1} (j = 1, 2, ..., i - 1, 且A[j] < A[i])。
贪心+二分查找:(O(nlogn))
开辟一个栈,每次取栈顶元素s和读到的元素a做比较,如果a>s, 则加入栈;如果a<s,则二分查找栈中的比a大的第1个数,并替换。 最后序列长度为栈的长度。
这也是很好理解的,对x和y,如果x<y且E[y]<E[x],用E[x]替换 E[y],此时的最长序列长度没有改变但序列Q的''潜力''增大。
举例:原序列为1,5,8,3,6,7
栈为1,5,8,此时读到3,则用3替换5,得到栈中元素为1,3,8, 再读6,用6替换8,得到1,3,6,再读7,得到最终栈为1,3,6,7 ,最长递增子序列为长度4。
用贪心+二分的方法很容易模拟出来,需要注意的就是二分的写法,而且需要输出最长上升子序列时,直接输出栈中的元素就行了。
#include <iostream> #include <cstdio> using namespace std; const int MAXN = 500000 + 5; int s[MAXN]; //s[]数组用来模拟栈 int binsearch(int *a, int l, int r, int val) { while (l <= r) { int mid = (l + r) >> 1; if (val < a[mid]) r = mid - 1; else if (val > a[mid]) l = mid + 1; else return mid; } return l; } int main() { int n, p, r, a[MAXN]; s[0] = INT_MIN; int icase = 0; while (scanf("%d", &n) != EOF) { ++icase; for (int i = 0; i < n; ++i) { scanf("%d %d", &p, &r); a[p] = r; } int val, t = 1; //t标记数组最后一个元素的下一位置,起始为1 for (int i = 1; i <= n; ++i) { val = a[i]; if (val > s[t-1]) s[t++] = val; else s[binsearch(s, 1, t - 1, val)] = val; } if (t - 1 == 1) printf("Case %d:\nMy king, at most %d road can be built.\n\n", icase, t - 1); else printf("Case %d:\nMy king, at most %d roads can be built.\n\n", icase, t - 1); } return 0; }
相关文章推荐
- hdu 1025 Constructing Roads In JGShining's Kingdom(最长上升子序列(LIS)O(nlogn)算法)
- HDU - 1025 Constructing Roads In JGShining's Kingdom(最长单调子序列 nlogn)
- 最长上升子序列(LIS)长度的O(nlogn)算法
- HDU-1950-Bridging signals【最长上升子序列(LIS)长度的O(nlogn)算法】
- hdu 5125 二分nlogn求最长上升子序列(LIS)+dp
- hdu 1025 Constructing Roads In JGShining's Kingdom 深夜又一波DP,最长上升子序列(O(nlogn)算法)!尼玛坑爹的输出啊!!
- 最长上升子序列(LIS)长度的O(nlogn)算法
- 最长递增子序列(LIS)的O(NlogN)打印算法
- hdu 1025 Constructing Roads In JGShining's Kingdom LIS最长上升序列
- HDU 1025(Constructing Roads In JGShining's Kingdom)最长不降子序列nlogn
- poj 2533(最长上升子序列)(n^2 ) 和 nlogn的算法
- 杭电ACM OJ 1025 Constructing Roads In JGShining's Kingdom 最长上升子序列 O(nlogn)算法详解+回溯暴力解决+动态规划dp优雅解决
- nlogn的最长上升子序列的算法(LIS)
- HDU 1025 Constructing Roads In JGShining's Kingdom(LIS的O(nlogn)算法)
- 最长上升子序列(LIS)(HDU 1025)
- 最长上升子序列(LIS)的O(nlogn) & O(n^2)算法 - 动态规划
- 最长上升子序列(LIS)长度的O(nlogn)算法
- 最长上升子序列(LIS)长度的O(nlogn)算法
- 最长上升子序列(LIS)长度的O(nlogn)算法
- hdu 1025 Constructing Roads In JGShining's Kingdom 最长上升序列nlogn