pku 3298 Antimonotonicity

题目来源: 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 ExpandedBlockStart.gif Code
 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 ExpandedBlockStart.gif Code
 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 }

转载于:https://www.cnblogs.com/cherip/archive/2008/09/21/1295310.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值