1215 数组的宽度

1215 数组的宽度

题目来源: Javaman

基准时间限制:1 秒 空间限制:131072 KB 分值: 80

收藏

关注

N个整数组成的数组,定义子数组a[i]..a[j]的宽度为:max(a[i]..a[j]) - min(a[i]..a[j]),求所有子数组的宽度和。

Input

第1行:1个数N,表示数组的长度。(1 <= N <= 50000)
第2 - N + 1行:每行1个数,表示数组中的元素(1 <= A[i] <= 50000)

Output

输出所有子数组的宽度和。

Input示例

5
1
2
3
4
5

Output示例

20思路:单调栈;我们只要统计每个数做为最小的数和最大的数所在区间有多少个。这样求当前数作为最大的数左右范围,这个用单调栈维护下,同理最小的也是然后左区间大小乘右区间大小就是这个数作为最大的出现的区间数;

以1 5 4 2 3为例,逐个入栈计算每个数的右边界:

1入栈 => 1

5入栈,前面所有比5小的出栈,并将右边界设为5 => 5 (确定了1的右边界是5,对应下标为1)

4入栈,前面所有比4小的出栈,并将右边界设为4 => 5 4

2入栈,前面所有比2小的出栈,并将右边界设为2 => 5 4 2

3入栈,前面所有比3小的出栈,并将右边界设为3 => 5 4 3(确定了2的右边界是3,对应下标为4)

最后所有数出栈,将5 4 3这3个数的右边界的下标设为5。

这样可以确认,每个数字最多进一次栈出一次栈,所有复杂度是O(n)的。

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<string.h>
  5 #include<math.h>
  6 #include<stack>
  7 #include<set>
  8 #include<queue>
  9 using namespace std;
 10 typedef long long LL;
 11 typedef struct node
 12 {
 13         int x;
 14         int id;
 15 } ss;
 16 LL ans[60000];
 17 int ll[60000];
 18 int rr[60000];
 19 stack<ss>stcx;
 20 int main(void)
 21 {
 22         int n,m;
 23         while(scanf("%d",&n)!=EOF)
 24         {
 25                 int i,j;
 26                 LL sum = 0;
 27                 for(i = 1; i <= n; i++)
 28                 {
 29                         scanf("%lld",&ans[i]);
 30                 }
 31                 while(!stcx.empty())
 32                         stcx.pop();
 33                 for(i = 1; i  <= n; i++)
 34                 {
 35                         while(!stcx.empty())
 36                         {
 37                                 ss ad = stcx.top();
 38                                 if(ad.x >= ans[i])
 39                                 {
 40                                         ss ak;
 41                                         ll[i] = ad.id+1;
 42                                         ak.id = i;
 43                                         ak.x = ans[i];
 44                                         stcx.push(ak);
 45                                         break;
 46                                 }
 47                                 else
 48                                 {
 49                                         stcx.pop();
 50                                         rr[ad.id] = i-1;
 51                                 }
 52                         }
 53                         if(stcx.empty())
 54                         {
 55                                 ll[i] = 1;
 56                                 ss ak;
 57                                 ak.x = ans[i];
 58                                 ak.id = i;
 59                                 stcx.push(ak);
 60                         }
 61                 }
 62                 while(!stcx.empty())
 63                 {
 64                         ss ak = stcx.top();
 65                         stcx.pop();
 66                         rr[ak.id] = n;
 67                         //printf("1\n");
 68                 }
 69
 70                 for(i = 1; i <= n; i++)
 71                 {
 72                         sum+=ans[i]*((rr[i]-i+1)*(i-ll[i]+1));
 73                 }
 74                      for(i = 1; i  <= n; i++)
 75                 {
 76                         while(!stcx.empty())
 77                         {
 78                                 ss ad = stcx.top();
 79                                 if(ad.x <=  ans[i])
 80                                 {
 81                                         ss ak;
 82                                         ll[i] = ad.id+1;
 83                                         ak.id = i;
 84                                         ak.x = ans[i];
 85                                         stcx.push(ak);
 86                                         break;
 87                                 }
 88                                 else
 89                                 {
 90                                         stcx.pop();
 91                                         rr[ad.id] = i-1;
 92                                 }
 93                         }
 94                         if(stcx.empty())
 95                         {
 96                                 ll[i] = 1;
 97                                 ss ak;
 98                                 ak.x = ans[i];
 99                                 ak.id = i;
100                                 stcx.push(ak);
101                         }
102                 }
103                 while(!stcx.empty())
104                 {
105                         ss ak = stcx.top();
106                         stcx.pop();
107                         rr[ak.id] = n;
108                 }
109                    for(i = 1; i <= n; i++)
110                 {
111                         sum-=ans[i]*((rr[i]-i+1)*(i-ll[i]+1));
112                 }
113                 printf("%lld\n",sum);
114         }
115         return 0;
116 }
				
时间: 2024-12-30 01:05:55

1215 数组的宽度的相关文章

51nod 1215 数组的宽度&amp;poj 2796 Feel Good(单调栈)

单调栈求每个数在哪些区间是最值的经典操作. 把数一个一个丢进单调栈,弹出的时候[st[top-1]+1,i-1]这段区间就是弹出的数为最值的区间. poj2796 弹出的时候更新答案即可 #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath

数组的宽度 单调栈

N个整数组成的数组,定义子数组a[i]..a[j]的宽度为:max(a[i]..a[j]) - min(a[i]..a[j]),求所有子数组的宽度和. 分析: 我们只要统计每个数做为最小的数和最大的数所在区间有多少个.这样求当前数作为最大的数左右范围,这个用单调栈维护下,同理最小的也是然后左区间大小乘右区间大小就是这个数作为最大的出现的区间数: 以1 5 4 2 3为例,逐个入栈计算每个数的右边界: 1入栈 => 1 5入栈,前面所有比5小的出栈,并将右边界设为5 => 5 (确定了1的右边界

51nod 1215 单调栈/迭代

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1215 1215 数组的宽度 题目来源: Javaman 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 N个整数组成的数组,定义子数组a[i]..a[j]的宽度为:max(a[i]..a[j]) - min(a[i]..a[j]),求所有子数组的宽度和. Input 第1行:1个数N,表示数组的长度.(1 <= N <=

【转】CUDA与二维动态数组

1 /* 2 * Copyright 徐洪志(西北农林科技大学.信息工程学院). All rights reserved. 3 * Data: 2012-4-22 4 */ 5 // 6 // 此程序是演示了二维动态数组空间申请和与显存数据相互拷贝的两种方法 7 #include <stdio.h> 8 //#include <cutil_inline.h> 9 #include <iostream> 10 #include <cuda_runtime.h>

c语言第一次作业

C语言是一门编程语言,简单点说,就是由人类书写按照一定规范书写的字符,通过一定手段(编译链接)转换后,可以让电脑或者其它电子芯片"读懂",并按照其要求工作的语言. 在所有的编程语言中,C语言是相对古老而原始的,同时也是在同类语言中更接近硬件,最为高效的编程语言.其应用广泛,设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言.目前C语言在底层开发,驱动编写,嵌入式开发等方面仍有着不可替代的地位. 而所谓C语言源代码,就是依据

由笛卡尔积现象分析数据库表的连接

首先,先简单解释一下笛卡尔积. 现在,我们有两个集合A和B. A = {0,1}     B = {2,3,4} 集合 A×B 和 B×A的结果集就可以分别表示为以下这种形式: A×B = {(0,2),(1,2),(0,3),(1,3),(0,4),(1,4)}: B×A = {(2,0),(2,1),(3,0),(3,1),(4,0),(4,1)}: 以上A×B和B×A的结果就可以叫做两个集合相乘的'笛卡尔积'. 从以上的数据分析我们可以得出以下两点结论: 1,两个集合相乘,不满足交换率,既

通过A*算法实现多节点的寻径

1 /* 2 A star 算法的基础处理 3 */ 4 #ifndef _A_STAR_BASE_H_ 5 #define _A_STAR_BASE_H_ 6 #include "windows.h" 7 8 typedef struct _APoint{ 9 int x; // x 坐标 10 int y; // y 坐标 11 int type; // 类型 12 int f; // f = g + h 13 int g; 14 int h; 15 } APoint, *PAPo

海量数据处理算法—Bloom Filter

1. Bloom-Filter算法简介 Bloom-Filter,即布隆过滤器,1970年由Bloom中提出.它可以用于检索一个元素是否在一个集合中. Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.它是一个判断元素是否存在集合的快速的概率算法.Bloom Filter有可能会出现错误判断,但不会漏掉判断.也就是Bloom Filter判断元素不再集合,那肯定不在.如果判断元素存在集合中,有一定的概率判断错误.

C语言学习----转义字符,常量

关于C语言的学习,主要分为语言.算法.数据结构.系统调用.设计几个大方面. 今天想和大家说的是  转义字符  和 常量 的一些简单知识 转义字符,说白了就是"/"+其他字符.基本的转义在这里就不一一介绍了,每一本资料上 应该都有.我现在想说一些容易出错的. 1.引号的输出 printf("\"");或者printf("%c",'"'); 单斜线的输出 printf("\\"); 2.如说我输出一串的路径的话