hdu 5489 LIS变形(删掉连续区间)
2016-01-04 17:17
369 查看
题目大意:给定一个序列长度为n,从中去掉长度为l的连续的序列,求剩余序列中的LIS,去掉的序列起始位置随意
思路:LIS变形,只要枚举去掉的所有区间就可以了,最大长度等于以区间右边第一个元素开始的LIS+区间左边的小于右边第一个元素的LIS-1.右边的直接逆序求LIS即可。
左边的常规LIS。左边的需要计算arr[i+l]在a[1……i]中的最大LIS就是我说的那个加法的后半部分。
ps:逆序求LIS有两种方法,第一种是将arr数组的所有元素取反,然后求。另外一种就是直接开始求,用upper_bound。本来前一天就该过得,但是初始化时的INF开小了,为99999999 ,tmp数组初始化也小了为0,正确的应该是999999999 , -999999999.
代码1:
代码2:
思路:LIS变形,只要枚举去掉的所有区间就可以了,最大长度等于以区间右边第一个元素开始的LIS+区间左边的小于右边第一个元素的LIS-1.右边的直接逆序求LIS即可。
左边的常规LIS。左边的需要计算arr[i+l]在a[1……i]中的最大LIS就是我说的那个加法的后半部分。
ps:逆序求LIS有两种方法,第一种是将arr数组的所有元素取反,然后求。另外一种就是直接开始求,用upper_bound。本来前一天就该过得,但是初始化时的INF开小了,为99999999 ,tmp数组初始化也小了为0,正确的应该是999999999 , -999999999.
代码1:
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <fstream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <iomanip> using namespace std; #define maxn 500005 #define MOD 1000000007 #define mem(a , b) memset(a , b , sizeof(a)) #define LL long long #define xxx 1000000005 #define INF 999999999 int arr[maxn]; int b[maxn]; int dp[maxn] ; int g[maxn]; int main() { int t; int ncase = 1; scanf("%d" , &t); while(t--) { int n , l , k; scanf("%d %d" , &n , &l); for(int i = 1 ; i <= n ; i ++) { scanf("%d" , &arr[i]); b[i] = -arr[i]; } mem(dp , 0); for(int i = 0 ; i <= n ; i ++) g[i] = INF; // mem(g , 0x7f); for(int i = n ; i > l ; i --) //逆序LIS { k = lower_bound(g+1 , g+n+1 , b[i]) - g; dp[i] = k; g[k] = b[i]; } // mem(g , 0x7f); for(int i = 0 ; i <= n ; i ++) g[i] = INF; int ans = 0 , maxlen = 0 ; for(int i = 1 ; i <= n - l ; i ++) { k = lower_bound(g+1 , g+n+1 , arr[i+l]) - g; ans = max(ans , k + dp[i+l] - 1); //重算了i+l位置的元素,所以需要减1 k = lower_bound(g+1 , g+n+1 , arr[i]) - g; g[k] = arr[i]; maxlen = max(maxlen , k); } ans = max(ans , maxlen); //区间是最后的一段,上面个的代码不能比较,需要单独比较 printf("Case #%d: %d\n" , ncase++ , ans); } return 0; }
代码2:
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <fstream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <iomanip> using namespace std; #define maxn 500005 #define MOD 1000000007 #define mem(a , b) memset(a , b , sizeof(a)) #define LL long long #define xxx 1000000005 #define INF 999999999 int dp[maxn]; int dp2[maxn]; int g[maxn]; int tmp[maxn]; int arr[maxn]; int per[maxn]; int main() { int t; int ncase = 1; scanf("%d" , &t); while(t--) { int n , l; scanf("%d %d" , &n , &l); for(int i = 1 ; i <= n ; i ++) { scanf("%d" , &arr[i]); } for(int i = 0 ; i <= n ; i ++) g[i] = INF ,tmp[i] = -INF; mem(dp,0); mem(dp2,0); mem(per , 0); int ans = 0; int len = 0; for(int i = 1 ; i <= n - l; i ++) { if(i + l <= n) ///求区间右边第一个数在左边的位置 { int k2 = lower_bound(g + 1, g + n + 1 , arr[i+l]) - g; per[i+l] = k2; } int k = lower_bound(g +1, g + n +1, arr[i]) - g; dp[i] = k; g[k] = arr[i]; len = max(len , k); } ans = max(per , len); for(int i = n; i > l ; i --) //求逆序LIS { int k = upper_bound(tmp + 1, tmp + n + 1, arr[i]) - tmp; dp2[i] = n+1 - (k - 1) ; tmp[k -1] = arr[i]; } for(int i = l + 1 ; i <= n ; i ++) { int res = per[i] + dp2[i] - 1; ans = max(res , ans); } ans = max(ans , dp[n-l]); printf("Case #%d: %d\n" , ncase++ , ans); } return 0; }
相关文章推荐
- jquery获取radiobutton的选中值
- 使用ThinkPHP上传类处理KindEditor上传的图片(主要是注意返回格式的方式)
- springmvc数组参数传递
- jQuery插件之ajaxFileUpload
- 设计模式系列16---响应请求的责任链模式
- extjs判断文件后缀的方法
- 实例详解jQuery结合GridView控件的使用方法
- 帝国cms投票时,提示此投票不存在,附解决办法
- PHP 替换WORD模板 实现可直接打印的WORD
- 在编译好的PHP环境中安装PHP扩展模块
- 微信公众平台开发(104) 自定义菜单扫一扫、发图片、发地理位置 - 方倍工作室
- jq:get获取json数据并以表格形式生成到页面
- 逻辑回归(详细版本)
- Android多线程下载原理
- 在控制台里打印controller的层级
- 设计模式系列15---构表分离的建造者模型
- Android多线程下载原理
- Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)
- QT自绘最小化最大化拖动
- Atitit. 订单管理 收银单持久化 功能设计 基于ecshop订单结构