/* 我一直陷入了出题者的思维,总是觉得这不是普通的LIS,而是要求最少有几个LIS。 现在回过头来看看,发现自己错了,确实就是最普通的LIS,只是我刚开始一直没有转过弯来。 可以这样理解这个LIS: 这个序列中的任何两个导弹都不能共用一个拦截系统, 而且其余的导弹都能和这个最长序列中的某个导弹分为同一组。 */ #include<iostream> #include<algorithm> #include<vector> #include<string> using namespace std; bool run() { int n; if(scanf("%d",&n)==EOF) return false; int a[10001],b[10001]; int i,j,len,max=-1; for(i=0;i<n;i++) scanf("%d",&a[i]); b[0]=1; for(i=1;i<n;i++) { len=0; for(j=0;j<i;j++) { if(a[i]>=a[j] && b[j]>len) len=b[j]; //注意等号的情况 } b[i]=len+1; } for(i=0;i<n;i++) { if(b[i]>max) max=b[i]; } printf("%d/n",max); return true; } int main() { while(run()); return 0; } 下面这道我认为很类似,但要转个弯,而且要用到LIS的nlogn算法,觉得蛮有价值,就放到一起来了。 /* 先将宽度由大到小排序,然后计算高度的LIS */ #include<iostream> #include<algorithm> #include<vector> #include<string> using namespace std; const int N=20001; int F[N],b[N],n; struct jsj { int width; int height; }t[N]; bool cmp(jsj x,jsj y) { if(x.width!=y.width) return x.width>y.width; else return x.height<y.height; //注意这里,相等的时候是套不住的,所以要排前面 } int binary(int num,int k) { int low=1,high=k; while(low<=high) { int mid=(low+high)/2; if(num>=b[mid]) low=mid+1; else high=mid-1; } return low; } int LIS() { int i,k=1; b[1]=F[0]; for(i=1;i<n;i++) { if(F[i]>=b[k]) b[++k]=F[i]; else { int pos=binary(F[i],k); b[pos]=F[i]; } } return k; } void run() { scanf("%d",&n); int i,j; for(i=0;i<n;i++) scanf("%d%d",&t[i].width,&t[i].height); sort(t,t+n,cmp); for(i=0;i<n;i++) F[i]=t[i].height; printf("%d/n",LIS()); } int main() { int t; scanf("%d",&t); while(t--) run(); return 0; }