CH895 最长上升子序列 题解报告

题目传送门

【题目大意】

给定一个长度为$n$的序列$\{a_n\}$,求最长上升子序列的长度。

【思路分析】

解法一:贪心(maybe?)

设$f_i$表示长度为$i$的上升子序列末尾数的最小值。

对于数列中的每一个数$x$,我们要找到最小的$f_i$,并且保证$f_i\ge x$,更新$f_i=x$。若已有的$f$数组中没有任何一个$f_i$满足$f_i\ge x$,那么就$f_{max_i+1}=x$。

然后我们可以发现$f$数组有一个神奇的性质,就是保证单调递增,于是我们可以稍微优化一下?

解法二:DP

设$f_i$表示以第$i$个数结尾的最长上升子序列的长度。

转移方程:$f_i=max\{f_j+1\}(a_i>a_j\&\&j\in[1,i-1])$,最后的答案为$max\{f_i\}(i\in[1,n])$

 解法三

应该还有一种解法?但是我不记得了QAQ

【代码实现】

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #define g() getchar()
 7 #define rg register
 8 #define go(i,a,b) for(rg int i=a;i<=b;i++)
 9 #define back(i,a,b) for(rg int i=a;i>=b;i--)
10 #define db double
11 #define ll long long
12 #define il inline
13 #define pf printf
14 using namespace std;
15 int fr(){
16     int w=0,q=1;
17     char ch=g();
18     while(ch<'0'||ch>'9'){
19         if(ch=='-') q=-1;
20         ch=g();
21     }
22     while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g();
23     return w*q;
24 }
25 int n,a[1002],f[1002],ans=1;
26 int main(){
27     //freopen("","r",stdin);
28     //freopen("","w",stdout);
29     n=fr();
30     go(i,1,n) a[i]=fr();f[1]=a[1];
31     go(i,2,n){
32         if(f[ans]continue;}
33         go(j,1,ans)
34             if(f[j]>=a[i]) {f[j]=a[i];break;}
35     }
36     pf("%d\n",ans);
37     return 0;
38 }
解法一

 

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #define g() getchar()
 7 #define rg register
 8 #define go(i,a,b) for(rg int i=a;i<=b;i++)
 9 #define back(i,a,b) for(rg int i=a;i>=b;i--)
10 #define db double
11 #define ll long long
12 #define il inline
13 #define pf printf
14 using namespace std;
15 int fr(){
16     int w=0,q=1;
17     char ch=g();
18     while(ch<'0'||ch>'9'){
19         if(ch=='-') q=-1;
20         ch=g();
21     }
22     while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g();
23     return w*q;
24 }
25 int n,a[1002],f[1002],ans=0;
26 int main(){
27     //freopen("","r",stdin);
28     //freopen("","w",stdout);
29     n=fr();
30     go(i,1,n) a[i]=fr(),f[i]=1;
31     go(i,1,n){
32         go(j,1,i-1) if(a[i]>a[j]) f[i]=max(f[i],f[j]+1);
33         ans=max(ans,f[i]);
34     }
35     pf("%d\n",ans);
36     return 0;
37 }
解法二

 

你可能感兴趣的:(CH895 最长上升子序列 题解报告)