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;}

原创粉丝点击