★ 问题描述:
小 D 最近很无聊 , 于是他拿来 N 个大小不一的球 , 然后他将球摆成一条直线 , 用 A1 …… An 表示球的体积大小。然后小 D 发现会有 Ai 和 Aj 之间的所有小球 Ak(i<k<j) 的体积都要比 Ai 大比 Aj 小。于是小 D 想找出这样的 Ai 和 Aj 满足以上条件并且 j-i 最大。小 D 向你求助 , 你能帮他么?★ 实验任务:
给出 Ai …… .Aj 的序列,要你找到满足对于 (i<k<j) 的 Ak 都大于 Ai 且小于 Aj, 并且 j-i 最大的 i,j 。 如果没找到请输出两个 -1 。
★ 数据输入 :
输入数据第一行包含一个整数 N 表示有 N <=100000 个球,接下来一行包含 N 个数 A1 …… An 表示每个球的体积。测试数据有多组数据,你必须处理到文件尾 (EOF)
★ 结果输出:
输出满足条件的 i 和 j, 中间用空格隔开。
输入示例: 输出示例:
6 2 68 2 7 5 6 11
2
7 5 -1 -1
算法思路:
每次查找最小值和最大值,将序列分为三段:
如果最小值刚好在最大值的左边:A1,A2....,Ai,Amin,...,Amax,Ak...Aj,则递归求A1到Ai,Ak到Aj的满足条件的最大值,中间段A max-Amin肯定是最大的,不用递归。
如果最小值在最大值的右边:A1,A2....,Amax,Ai...,Ak,Amin...Aj,则递归求A1到Amax,Ai到Ak,Amin到Aj的满足条件的最大值。
代码:
#include<stdio.h>
int a[100001]; //用于保存序列值
int L=0; //要求的下标相剪的最大值
int begin=0; //开始下标
int end=0; //结束下标
int n=0; //序列长度
//递归函数
void getL(int b,int e)
{
if(b>=0&&e<n&&(e-b)>1){//b要大于0,e要小于n,而且根据条件e和b肯定间隔要大于1
int i,l=-1;
int min,max;
int minIndex,maxIndex;
min=10000000;
max=-1;
minIndex=maxIndex=0;
for(i=b;i<=e;i++){//查找最小值和最大值
if(a[i]<min)
{
min=a[i];
minIndex=i;
}
if(a[i]>max)
{
max=a[i];
maxIndex=i;
}
}
/*分三种情况讨论:
如果最小值刚好在最大值的左边:A1,A2....,Ai,Amin,...,Amax,Ak...Aj,则递归求A1到Ai,Ak到Aj的满足条件的最大值,中间段A max-Amin肯定是最大的,不用递归。
如果最小值在最大值的右边:A1,A2....,Amax,Ai...,Ak,Amin...Aj,则递归求A1到Amax,Ai到Ak,Amin到Aj的满足条件的最大值。
*/
if((maxIndex-minIndex)>L)
{
L=maxIndex-minIndex;
begin=minIndex;
end=maxIndex;
}
if(maxIndex>minIndex)
{
if((minIndex-1)>b)
getL(b,minIndex-1);
if((maxIndex+1)<e)
getL(maxIndex+1,e);
}else{
if(maxIndex>b)
getL(b,maxIndex);
if((minIndex-1)>(maxIndex+1))
getL(maxIndex+1,minIndex-1);
if(e>minIndex)
getL(minIndex,e);
}
}
}
int main(int argc, char* argv[])
{
int i;
while(scanf("%d",&n)!=EOF){
L=0;
begin=0;
end=0;
for(i=0;i<n;i++)
scanf("%d",&a[i]);
getL(0,n-1);
if(L==0)//不存在题目要求的情况,输出"-1 -1"
printf("-1 -1\n");
else printf("%d %d\n",begin+1,end+1);//题目要求的下标和我们的数组下标差1,所以要加上去
}
return 0;
}