描述 Description
有N个整数,输出这N个整数的最长上升序列、最长下降序列、最长不上升序列和最长不下降序列。
输入格式 Input Format
第一行,仅有一个数N。 N<=700000
第二行,有N个整数。 -10^9<=每个数<=10^9
输出格式 Output Format
第一行,输出最长上升序列长度。
第二行,输出最长下降序列长度。
第三行,输出最长不上升序列长度。
第四行,输出最长不下降序列长度。
样例输入 Sample Input
10
1 3 0 8 6 2 3 1 4 2
样例输出 Sample Output
4
4
4
4
这道题因为数据量达到了700000,你要是写一个一般的DP绝对会超时的,所以就用二分查找来写,这道题虽然不是特别难,但却是分锻炼你的代码,而且还的注意一些细节
就是比方说有一个数组 6 5 4 3 2 1 1 1,那么你输出最长不上升序列长度就是8而不是6,最长不下降序列长度就是3而不是1.
血的教训:T.T(这道说练练快读吧,然后.....然后....MD少了2个等号,导致我一直不知道怎么错了,最后才发现数组不对,然后才AC)QAQ所以一定要细心
代码如下:
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<algorithm> #include<ctime> #define maxn 710000 using namespace std; int n; int a[maxn],f1[maxn],g1[maxn]; int f2[maxn],g2[maxn]; int f3[maxn],g3[maxn]; int f4[maxn],g4[maxn]; inline int read() { char ch=getchar(); int x=0,f=1; while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } int len; int search1(int x) { int left=0,right=len,mid; while(left+1<right) { mid=(left+right)/2; if(a[g1[mid]]<x) left=mid; else right=mid; } if(a[g1[right]]<x) left=right; return left; } void work1()//最长上升序列长度 { f1[1]=1; g1[1]=1; len=1; for(int i=2;i<=n;i++) { if(a[i]>a[g1[len]]) { len++; //cout<<a[i]<<' '; g1[len]=i; f1[i]=len; } else { int t=search1(a[i]); f1[i]=t+1; if(a[g1[t+1]]>a[i]) g1[t+1]=i; } } } int search2(int x) { int left=0,right=len,mid; while(left+1<right) { mid=(left+right)/2; if(a[g2[mid]]>x) left=mid; else right=mid; } if(a[g2[right]]>x) left=right; return left; } void work2()//最长下降序列长度 { f2[1]=1; g2[1]=1; len=1; for(int i=2;i<=n;i++) { if(a[i]<a[g2[len]]) { len++; //cout<<a[g2[len]]<<' '; g2[len]=i; f2[i]=len; } else { int t=search2(a[i]); f2[i]=t+1; if(a[g2[t+1]]<a[i]) g2[t+1]=i; } } } int search3(int x) { int left=0,right=len,mid; while(left+1<right) { mid=(left+right)/2; if(a[g3[mid]]>=x) left=mid; else right=mid; } if(a[g3[right]]>=x) left=right; return left; } void work3()//最长不上升序列长度 { f3[1]=1; g3[1]=1; len=1; for(int i=2;i<=n;i++) { if(a[i]<=a[g3[len]]) { len++; g3[len]=i; f3[i]=len; } else { int t=search3(a[i]); f3[i]=t+1; if(a[g3[t+1]]<=a[i]) g3[t+1]=i; } } } int search4(int x) { int left=0,right=len,mid; while(left+1<right) { mid=(left+right)/2; if(a[g4[mid]]<=x) left=mid; else right=mid; } if(a[g4[right]]<=x) left=right; return left; } void work4()//最长不下降序列长度 { f4[1]=1; g4[1]=1; len=1; for(int i=2;i<=n;i++) { if(a[i]>=a[g4[len]]) { len++; g4[len]=i; f4[i]=len; } else { int t=search4(a[i]); f4[i]=t+1; if(a[g4[t+1]]>=a[i]) g4[t+1]=i; } } } int main() { cin>>n; for(int i=1;i<=n;i++) { a[i]=read(); //cin>>a[i]; } work1(); cout<<len<<endl; work2(); cout<<len<<endl; work3(); cout<<len<<endl; work4(); cout<<len<<endl; return 0; }