题目来源: http://acm.pku.edu.cn/JudgeOnline/problem?id=3298
这到题目显然是一道DP题。
设:在求的数列中,如果这个数比左右的数大,则称为大值,反之为小值。
原先想到的是,对于每个数,设置2个值,一个为小值一个为大值。小值为前面所有比此数大的数的大值加1,如果为0个不用加了,因为第一个数必须为大值.大值为前面所有比此数小的数的小值+1.这个算法的时间复杂度为O(n^2)。TLE。
参考 大牛们的代码。设置2个值,mi,mx。表示一个数的为小值,和大值时串的长度。显然一个大值和小值的串的长度是相互递增的。即mi=max(mi,mx+1),
mx=max(mi+1,mx);设置一个标号值pre表示前一个值。比较当前值,如果小,则当前值为大值是的串长一定不会变化。只需要比较为小值时,串是否变化就行。反之同理。
其实这道题也就是求一串数组成的w型的拐角有多少个。并不需要关系具体是那几个数组成这样的拐角。
代码:
TLE版:
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <iostream>
2
3 using namespace std;
4
5 int num[30001][2];
6 int nn[30001];
7 int n;
8
9 int Max(int a,int b)
10 {
11 return a>b?a:b;
12 }
13
14 int main()
15 {
16 freopen("test.txt","r",stdin);
17 int t;
18 cin>>t;
19 while(t--)
20 {
21 scanf("%d",&n);
22 for(int i=0;i<n;i++) scanf("%d",&nn[i]);
23 num[0][0]=0;num[0][1]=1;
24 int m1=0,m2=0,mmx=1;
25 for(int i=1;i<n;i++)
26 {
27 m1=0,m2=0;
28 for(int j=i-1;j>=0;j--)
29 {
30 if(nn[j]<nn[i]) m1=Max(m1,num[j][0]);
31 if(nn[j]>nn[i]) m2=Max(m2,num[j][1]);
32 }
33 num[i][0]=m2==0?m2:m2+1;num[i][1]=m1+1;
34 mmx=Max(num[i][0],mmx);mmx=Max(num[i][1],mmx);
35 }
36 printf("%d\n",mmx);
37 }
38 }
AC版:
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <iostream>
2
3 using namespace std;
4
5 int Max(int x,int y)
6 {
7 return x>y?x:y;
8 }
9
10 int n,pre;
11
12 int main()
13 {
14 int t;
15 cin>>t;
16 while (t--)
17 {
18 scanf("%d%d",&n,&pre);
19 int u=-n,d=0,x;
20 for(int i=1;i<n;i++)
21 {
22 scanf("%d",&x);
23 if(x<pre) u=Max(u,d+1);
24 if(x>pre) d=Max(u+1,d);
25 pre=x;
26 }
27 printf("%d\n",Max(u,d)+1);
28 }
29 }