题目:
Description
有一个长度为N的整数序列,序列里面的数是两两不同的,现在要在里面找一个波动序列,这个序列越长越好。
比如有波动序列{a0,a1,a2…an},则a0 > a1 < a2 > a3 < …
Input
第一行输入一个数T,代表有T个任务,T不大于50。
对于每个任务,输入格式为
N a0 a1 a2 … aN
其中N<=30000,测试数据保证序列的数两两不同。
Output
对于每个任务,输出最长的波动序列长度
Sample Input
Sample Output
本题求解最长的波动序列,只要求a0>a1<a2......,并且题目中已经明确表示不存在两个数相等,所以不用考虑两个数相等的情况,因为N的最大值为3000,如果使用两重for循环,肯定会超时,所以以下求解为用一重for循环来求解。例如一串数(9)1,8,6,10,5,3,4,2;假如不包括数字9,则第一个数应该从8开始,因为1<8,所以只能从8开始,8也可以看做一个高点,接下来为6,6看做一个低点,接下来为10一个高点,接下来为5一个低点,因为3<5,所以最低点应该是3,接着为4,到现在,我们可以得到一串数字:8,6,10,3,4,2.高点为8,10,4,低点为6,3,2,虽然5为一个低点,但是3比5小,所以低点为3,最长的串为3+3=6;由此可以看出,只要计算出这个数字串的高点和低点即可。
程序代码如下:
#include<iostream>
using namespace std;
int a[30005]={0};
int main()
{
int T;
cin>>T;
while(T--)
{
int N;
cin>>N;
int i;
for(i=0;i<N;i++)
{
cin>>a[i];
}
int front=0,real=0; 计算最高点和最低点,front为高点计数,real为低点计数
int high;
if(a[0]>a[1]) 判断前两个数的大小,初步确定高低点
{
front++;
real++;
high=a[1];
}
else
{
front++;
high=a[1];
}
for(i=2;i<N;i++)
{
if((front+real)%2) 判断接下来一个数为">"还是小于"<",此处为“<”;
{
if(a[i]>high)
{
high=a[i];
}
else
{
high=a[i];
real++;
}
}
else
{
if(a[i]>high)
{
high=a[i];
front++;
}
else
{
high=a[i];
}
}
}
cout<<front+real<<endl;
}
return 0;
}
解题感想:
这道题当初拿起来看是,就直接去找模板去了,可是找了好长时间还是没有,修改模板也不行,还是学长要把这道题讲完的时候画的一个图,让我知道了怎么来做这道题,其实这道题跟找一个数组中最大的递减数列不一样,那道题还是有模板的,这道题还是第一次遇到,不过还好现在就解决了,以后遇到类似的题目,可以直接来解决了。这道题的解题思路主要是画出一个上下波动的线段即可。这样就可以看出来了。