UVA
来源:互联网 发布:淘宝漫画图 编辑:程序博客网 时间:2024/06/05 21:04
题意:给定一个长度为n的整数序列a,求一个最长子序列,使得该序列的长度为2*k+1,前k+1个数严格递增,后k+1个数严格递减。
思路:用二分法求最长上升子序列。问题转化为求以i结尾的最长上升子序列和以i开始的最长递减子序列,而以i开始的最长递减子序列可以看作从n开始以i结尾的最长上升子序列。用dp[i]表示长度为i的子序列尾部元素的最小值,显然dp[i]为递增的,那么就可以二分查找了。用num[i]表示以a[i]结尾的最长子序列的长度。先从1-n求一遍num1[i],在从n-1求一遍num2[i],则答案为max(2 * min(num1[i], num2[i]) + 1);
从dp数组找第一个大于a[i]的数dp[t],用a[i]替换,则t就为num[i]。
#include <cstdio>#include <algorithm>#include <iostream>#include<vector>#include<cmath>#include<set>#include<cstring>#include<map>using namespace std;typedef long long ll;const int maxn = 21e2 + 10;const int maxt = 100200;const int inf = 0x3f3f3f3f;const ll INF = 0x7f7f7f7f7f;const int mod = 1e9 + 7;const double pi = acos(-1.0);const double eps = 1e-8;int a[10010], b[10010];int num1[10010], num2[10010];int dp1[10010], dp2[10010];int n;int main(){ while(~scanf("%d", &n)){ for(int i = 0; i < n; ++i){ scanf("%d", &a[i]); b[n - i - 1] = a[i]; } memset(dp1, inf, sizeof dp1); memset(dp2, inf, sizeof dp2); for(int i = 0; i < n; ++i){ int t1 = lower_bound(dp1, dp1 + n, a[i]) - dp1; num1[i] = t1; dp1[t1] = a[i]; int t2 = lower_bound(dp2, dp2 + n, b[i]) - dp2; num2[i] = t2; dp2[t2] = b[i]; } int ans = 1; for(int i = 0; i < n; ++i){ ans = max(ans, 2 * min(num1[i], num2[n - i - 1]) + 1); } printf("%d\n", ans); } return 0;}
1 0
- uva
- UVA
- UVA
- UVA
- uva
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- UVA
- 美国发生机器人致人死亡事件,维修技师头骨被击碎
- hdu 4292 Food 【图论-网络流-最大流-Dinic】
- 2017年4月21日华为笔试题 德州扑克
- 【51nod 1092 回文字符串】+ LCS
- 连接器脚本解析
- UVA
- 文件隐写
- 自考总结之心情整理
- UVA
- Servlet的部署,生命周期---昨天--4月20号学习总结
- wireshark找不到网卡的解决办法
- 蒙特卡罗(Monte Carlo)方法简介
- easyui使用总结(一)
- Cannot create directory: /home/lrh/.vim/view.