A. 智能飞弹
时间限制(普通/Java) : 2000 MS/ 6000 MS 运行内存限制 : 65536 KByte
总提交 : 253 测试通过 : 56
总提交 : 253 测试通过 : 56
比赛描述
魁拔军团为抵御神界的攻击,在涡流岛上自顶向下建立了N道防御屏障,第i道屏障能量厚度为Di。神界势要灭掉魁拔,发明了一种能在行进路径上挑选可击破屏障进行击破的智能飞弹,这种飞弹的优点是可以击破并不连续存在的屏障,缺点是飞弹击破的下一道屏障的能量厚度必须严格小于当前击破的一道,且飞弹只能从上往下逐次击破而不能倒飞。比如有5道屏障,自上而下能量厚度分别为5,3,4,2,1,则一个可行的击破序列为5,4,2,1,并且这也是最长的一个可击破序列,另一个序列如5,3,4由于位于后方的屏障厚度为4大于其前方的屏障,所以是个不能击破的序列。
现在给出魁拔的屏障设置,求最长可击破的序列长度。
现在给出魁拔的屏障设置,求最长可击破的序列长度。
输入
第一行包含一个正整数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);
}
}