HDU 1025 最大递增子序列长度
来源:互联网 发布:盛世赢家炒股软件 编辑:程序博客网 时间:2024/06/10 02:20
这道题目一开始我的是复杂度为 n^2的DP,发现超时了,于是去学了,nlgn的DP+二分的方法,一开始样例过了,我还以为自己写对了,后来交上去却WA了,原来对这个还是理解不是太深,写起来有个地方没有理解清楚后来慢慢看懂了!!!!其实这个原理很简单,就是先比较一头一尾,然后进行二分,找到其中第一个比他大的数,然后拿这个数替换掉那个比他大的数,一直进行这样,时间就会减少!!!!代码如下:#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn=500005;int a[maxn],f[maxn];int n;int bsearch(int* f,int x,int& a) { int left=1; int right=x; while(left<=right) { int mid=(left+right)>>1; if(f[mid-1]<a&&a<=f[mid])return mid; else if(a>f[mid])left=mid+1; else right=mid-1; }}int LIS(int* a,int n) { int size=2; f[1]=a[1]; int j=1; for(int i=2; i<=n; i++) { if(a[i]<=f[1]) {//一开始这里写错了,其实很好理解的,就是先去一头一尾进行判断,然后对中间的进行二分 j=1; } else if(a[i]>=f[size-1]) j=size++; else j=bsearch(f,size,a[i]); f[j]=a[i]; } return size-1;}int main() { int tcase=0; while(scanf("%d",&n)!=EOF) { memset(a,0,sizeof(a)); for(int i=1; i<=n; i++) { int x,y; scanf("%d%d",&x,&y); a[x]=y; } int ans; ans=LIS(a,n); printf("Case %d:\n",++tcase); if(ans<=1) { printf("My king, at most %d road can be built.\n\n",ans); } else { printf("My king, at most %d roads can be built.\n\n",ans); } } return 0;}