hdu 5489(LIS最长上升子序列)
来源:互联网 发布:编程入门语言 编辑:程序博客网 时间:2024/06/05 11:05
题意:一个含有n个元素的数组,删去k个连续数后,最长上升子序列 /*思路参考GoZy
思路: 4 2 3 [5 7 8] 9 11 ,括号表示要删掉的数,
所以 最长上升子序列 = ] 右边数A的lis + [左边最大值小于A的lis
即相当于枚举删除的所有情况,并求它们的LIS,取最大值
如本例 : 最长 = 2[ 9 11] + 2[2 3], 然后将框从左往右移,算出最大值
用nlog(n)求LIS:
对于a[i],在arr数组中用log(n)找到比它小的数的个数x,arr[x] = a[i] ,arr保存的到当前位置的最长LIS
#include <cstdio>#include <cstring>#include <algorithm>#include <functional>#include <vector>#include <queue>#define MAXN 100010typedef long long ll;using namespace std;const int N = 1e5 + 5;int a[N];int b[N];int d1[N]; //表示i处的LISint arr[N];int main(){ int t,cas = 1; int n,len; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&len); for(int i = 0; i <= n-1; i++) { scanf("%d",&a[i]); b[i] = -a[i]; //为求右边的LIS } memset(arr,0x3f3f3f,sizeof(arr)); for(int i = n-1; i >= 0; i--) //nlog(n)求LIS { int x = lower_bound(arr,arr+n,b[i]) - arr; //用log(n)查找,也可二分 arr[x] = b[i]; d1[i] = x+1; } int ans = 0,tlen = 0; memset(arr,0x3f3f3f,sizeof(arr)); for(int i = len; i < n; i++) //arr中保存框左边的数最长lis { int x = lower_bound(arr,arr+n,a[i]) - arr; //在前面找最大值比a[i]小的最长LIS ans = max(ans,x + d1[i]); x = lower_bound(arr,arr+n,a[i - len]) - arr; arr[x] = a[i - len]; tlen = max(x+1,tlen); //记录左边的最长长度 } printf("Case #%d: ", cas++); ans = max(ans,tlen); //比较全在框左边的情况 printf("%d\n",ans); } return 0;}
ps.如果没有东西值得你为之努力,那你和一条咸鱼有什么区别?
0 0
- hdu 5489(LIS最长上升子序列)
- 最长上升子序列(LIS)(HDU 1025)
- 最长上升子序列LIS
- 最长上升子序列LIS
- 最长上升子序列(LIS)
- 最长上升子序列 LIS
- 最长上升子序列(LIS)
- LIS最长上升子序列
- 最长上升子序列 LIS
- 最长上升子序列LIS
- LIS最长上升子序列
- 最长上升子序列LIS
- LIS 最长上升子序列
- 最长上升子序列LIS
- LIS(最长上升子序列)
- LIS 最长上升子序列
- lis 最长上升子序列
- LIS-最长上升子序列
- CATransition-转场动画
- 回忆录之软件管理
- web前端,jquery实现瀑布流(鼠标滚动不断加载)
- abc
- LintCode-O(1)检测2的幂次
- hdu 5489(LIS最长上升子序列)
- 黑马程序员—面向对象知识总结
- sqrt函数实现
- 移动端web页面自适应和rem
- 文章索引-视频编解码
- 理性的来源
- kvm文件默认路径
- uva 12716 打表找规律
- C++容器(三):pair类型