这道题目一开始我的是复杂度为 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;
}
HDU 1025 最大递增子序列长度
最新推荐文章于 2021-08-01 19:35:31 发布