https://www.luogu.org/fe/problem/P1020
第一种:树状数组
int lowbit(int x){return x&-x;}
void add(int x,int c){
for(int i=x;i<=maxn;i+=lowbit(i)) f[i]=max(f[i],c);//维护最大值
}
int query(int x){
int res=0;
for(int i=x;i>=1;i-=lowbit(i)) res=max(res,f[i]);//求以小于等于x的数为结尾的最长不上升子序列的长度的最大值
return res;
}
int main(){
while(scanf("%d",&a[++n])!=EOF) maxn=max(maxn,a[n]);
n--;//要-1,不然n就不是正确的n了
for(int i=n;i>=1;i--){//从后往前循环
int q=query(a[i])+1;//查询以小于等于x的数为开头的最长不上升子序列的长度的最大值
add(a[i],q);//这个最大值+1就是以当前这个数开头的最长不上升子序列的长度,丢到树状数组里面去
ans1=max(ans1,q);
}
printf("%d\n",ans1);
memset(f,0,sizeof(f));//还是memset一下比较保险
for(int i=1;i<=n;i++){//从前往后循环
int q=query(a[i]-1)+1;//查询以小于(没有等于!!!)x的数为结尾的最长上升子序列的长度的最大值
add(a[i],q);//这个最大值+1就是以当前这个数结尾的最长上升子序列的长度,丢到树状数组里面去
ans2=max(ans2,q);
}
printf("%d\n",ans2);
}
int a[N],d1[N],d2[N],n;
int main() {
while(cin>>a[++n]);n--; //输入
int len1=1,len2=1; //初始长度为1
d1[1]=a[1]; //用于求不上升序列长度
d2[1]=a[1]; //用于求上升序列长度
for(int i=2; i<=n; i++) { //从a[2]开始枚举每个数(a[1]已经加进去了)
if(d1[len1]>=a[i])d1[++len1]=a[i]; //如果满足要求(不上升)就加入d1
else { //否则用a[i]替换d1中的一个数
int p1=upper_bound(d1+1,d1+1+len1,a[i],greater<int>())-d1;
d1[p1]=a[i];
}
if(d2[len2]<a[i])d2[++len2]=a[i]; //同上
else {
int p2=lower_bound(d2+1,d2+1+len2,a[i])-d2;
d2[p2]=a[i];
}
}
cout<<len1<<endl<<len2; //输出
return 0; //结束
}