POJ_2559

来源:互联网 发布:最小生成树kruskal算法 编辑:程序博客网 时间:2024/06/12 23:36

//============================================================================
// Name        : POJ_2559.cpp
// Author      : tiger
// Version     :
// Copyright   : 暴搜即可,对于每一个位置i分为向左向右延伸,直到遇到s[p]<s[i],s[q]<s[i]
//    这样区间为q-p-1,注意从数组下标1开始存,并且初始化s[0]=s[n+1]=-1;
//    保证两头最小,区间就肯定是q-p-1,不用分类讨论了
//    直接暴搜会超时,需要优化,
//    注意当向左延伸时,如果是s[p]>=s[i],那么定有
//    s[ letf[p]  + 1] ~ s[p] >= s[i] -> p = left[p] -> 再比较是s[p]与s[i],
//    直到s[p]<s[i],此时left[i]=p。
//    当向右延伸时,可将数组反转,用同上地方法即可,详细可参考源代码
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <stdio.h>
int r[100005];//反转数组
int left1[100005];
int left2[100005];
int s[100005];//原数组
int main()
{

 freopen("in", "r", stdin);
 int i, p, n;
 __int64 max, m;
 s[0] = -1;
 r[0] = -1;
 while (scanf("%d", &n) && n)
 {
  for (i = 1; i <= n; i++)
  {
   scanf("%d", s + i);
   r[n+1-i] = s[i];//反转
  }
  max = 0;
  s[n + 1] = -1;
  r[n + 1] = -1;
  left1[1] = 0;
  left2[1] = 0;
  //原数组向左延伸
  for (i = 1; i <= n; i++)
  {

    p = i-1;
    while (s[p] >= s[i])
     p = left1[p];
    left1[i] = p;

  }
  //反转数组向左延伸
  for (i = 1; i <= n; i++)
  {

    p = i-1;
    while (r[p] >= r[i])
     p = left2[p];
    left2[i] = p;

  }
  //计算面积
  for (i = 1; i <= n; i++)
  {
   //注意位置的转变,s[i] == r[n-i+1]
   m =  (__int64)( (n-left2[n-i+1]+1 ) -left1[i] -1)* (__int64)s[i];
   if(m >max)
    max= m;
  }
  printf("%I64d/n", max);
 }

 return 0;
}

原创粉丝点击