SDUT_DP 1003
一道简单的求解最长上升子序列的问题。感觉这道题的巧妙之处就是在查找最长上升子序列的时候用到了变形的二分查找。很是巧妙,因为一般的找上升子序列的方法,用于这道题是超时的。
巧妙的代码为:
else { int l=1; int h=max; while(l<=h) { int mid=(l+h)/2; if(flag[mid]>a[i].r) { if(flag[mid-1]<a[i].r) { flag[mid]=a[i].r;break; } else h=mid-1; } else l=mid+1; } }
下面是这道题的完整代码,具体的就不解释了,这道题很简单,一开就明白了
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; #define N 500001 int flag[N]; struct node { int p,r; }a[N]; int cmp(node a,node b) { if(a.p!=b.p) return a.p<b.p; else return a.r<b.r; } int main() { int n,i; int max; int cs=0; while(cin>>n) { memset(flag,0,sizeof(flag)); for(i=1;i<=n;i++) scanf("%d%d",&a[i].p,&a[i].r); sort(a+1,a+n+1,cmp); flag[1]=a[1].r; flag[0]=0; max=1; for(i=2;i<=n;i++) { if(a[i].r>flag[max]) { max++; flag[max]=a[i].r; } else { int l=1; int h=max; while(l<=h) { int mid=(l+h)/2; if(flag[mid]>a[i].r) { if(flag[mid-1]<a[i].r) { flag[mid]=a[i].r;break; } else h=mid-1; } else l=mid+1; } } } cout<<"Case "<<++cs<<":"<<endl; if(max==1) printf("My king, at most %d road can be built.\n\n",max); else printf("My king, at most %d roads can be built.\n\n",max); } return 0; }