比赛描述
输入
第一行包含一个正整数T(T≤100),表示样例个数,接下来给出T组测试用例。
每组测试用例包含两行,第一行为一个正整数N(1≤N≤100000),表示有N道屏障,第二行有N个用空格隔开的正整数Di(1≤Di≤100000),表示自上而下各道屏障的能量厚度。
输出
每组测试用例输出一行结果,包含一个整数,表示最长可击破的序列长度。
样例输入
2
5
5 3 4 2 1
5
1 1 1 1 1
样例输出
4
1
提示
题目来源
ACM爱好者协会
/* Time Limit Exceed at Test 2 #include<stdio.h> int h[100000],m[100000]; int main(){ int T,N,i,j,max; scanf("%d",&T); while(T--){ scanf("%d",&N); for(i=0;i<N;i++){ scanf("%d",h+i); } max=1; for(i=0;i<N;i++){ m[i]=1; for(j=0;j<i;j++){ if(h[i]<h[j] && m[i]<m[j]+1){ m[i]=m[j]+1; } } if(m[i]>max){ max=m[i]; } } printf("%d\n",max); } } */ /* 427MS // LIS(Longest Increasing Subsequence,LIS) O(nlogn) 的算法 #include<stdio.h> #define MAX_N 100001 int h[MAX_N]; // 第 i 个建筑的高度 int b[MAX_N]; // 长度为 i 的LIS 尾元素的最大值 int len; // b[]数组的长度,数组是排好序的,由大到小 int find(int n){ int l=1,r=len,mid; while(l<=r){ mid = (l+r)>>1; if(b[mid]>n){ l = mid+1; // 找到 >n 的最后一个b[i],b[i+1]放n, }else{ r = mid-1; } } return l; } int main(){ // freopen("test.txt","r",stdin); int T,N,i,j; scanf("%d",&T); while(T--){ scanf("%d",&N); len = 0; for(i=1;i<=N;i++){ scanf("%d",h+i); } for(i=1;i<=N;i++){ j = find(h[i]); b[j] = h[i]; if(j>len){ len = j; } } // for(j=1;j<=len;j++){ // printf("len = %d,max tail = %d\n",j,b[j]); // } printf("%d\n",len); } } */ // 137MS #include<stdio.h> #define MAX_N 100001 int h[MAX_N]; int b[MAX_N]; int len; int getNum(){ int t,r; while((t=getchar())<'0' || t>'9'); r = t-'0'; while((t=getchar())>='0' && t<='9'){ r = r*10 + t-'0'; } return r; } int find(int n){ int l=1,r=len,mid; while(l<=r){ mid = (l+r)>>1; if(b[mid]>n){ l = mid+1; }else{ r = mid-1; } } return l; } int main(){ int T,N,i,j; // scanf("%d",&T); T = getNum(); while(T--){ // scanf("%d",&N); N = getNum(); len = 0; for(i=1;i<=N;i++){ // scanf("%d",h+i); h[i] = getNum(); } for(i=1;i<=N;i++){ j = find(h[i]); b[j] = h[i]; if(j>len){ len = j; } } printf("%d\n",len); } }