码迷,mamicode.com
首页 > 其他好文 > 详细

51nod 1215 单调栈/迭代

时间:2017-08-22 23:03:53      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:枚举   ges   修改   tput   分享   red   计算   时空   group   

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 <= 50000)
第2 - N + 1行:每行1个数,表示数组中的元素(1 <= A[i] <= 50000)
Output
输出所有子数组的宽度和。
Input示例
5
1
2
3
4
5
Output示例
20
感觉很经典的题目。
首先我们不可能枚举出所有的子区间,显然时空是不允许的,那就要从元素入手,我们只要知道每个元素被作为最大最小值得次数答案就出来了,问题转化为求元素作为最值的次数。
可以找到当前元素作为最大/小值时对应的最大的区间左右端点,然后组合计算一下就是答案了。找这个左右端点时可以用单调栈也可以迭代搜索,stl貌似要慢一些。
正确性在于找端点时满足决策单调性,例如找最大值左端点时,这个元素左侧的元素如果大于他,那显然左端点就是他本身了,此时就是一个单调递减栈,大于栈顶元素时左端点就可以用栈顶
元素的左端点代替;
总之就一句话,大于左侧的元素,一定大于所有左侧元素能大于的元素。
还有就是第一次WA了因为重复计算了, 只要稍微修改一下为左侧不严格右侧严格的查找就好了。
 1 #include <iostream>
 2 #include<algorithm>
 3 #include<stack>
 4 #include<cstdio>
 5 using namespace std;
 6 typedef long long LL;
 7 const int MAX = 50005;
 8 int a[MAX], l1[MAX], r1[MAX], l2[MAX], r2[MAX];
 9 int maxt[MAX], mint[MAX];
10 stack<int>S;
11 int main()
12 {
13     int N, i, j, k;
14     scanf("%d", &N);
15     for (i = 1;i <= N;++i) scanf("%d", a + i);
16     for (i = 1;i <= N;++i)
17     {
18         if (S.empty() || a[i] < a[S.top()]) {
19             l1[i] = i;
20             S.push(i);
21         }
22         else {
23             while (!S.empty() && a[S.top()] <= a[i]) {
24                 l1[i] = l1[S.top()];
25                 S.pop();
26             }
27             S.push(i);
28         }
29     }while (!S.empty()) S.pop();
30     for (i = N;i >=1;--i)
31     {
32         if (S.empty() || a[i] <= a[S.top()]) {
33             r1[i] = i;
34             S.push(i);
35         }
36         else {
37             while (!S.empty() && a[S.top()] < a[i]) {
38                 r1[i] = r1[S.top()];
39                 S.pop();
40             }
41             S.push(i);
42         }
43     }while (!S.empty()) S.pop();
44     for (i = 1;i <= N;++i)
45     {
46         maxt[i] += (r1[i]-l1[i])+(i-l1[i])*(r1[i]-i);
47     }
48     for (i = 1;i <= N;++i)
49     {
50         if (S.empty() || a[i] > a[S.top()]) {
51             l2[i] = i;
52             S.push(i);
53         }
54         else {
55             while (!S.empty() && a[S.top()] >=a[i]) {
56                 l2[i] = l2[S.top()];
57                 S.pop();
58             }
59             S.push(i);
60         }
61     }while (!S.empty()) S.pop();
62     for (i = N;i>=1;--i)
63     {
64         if (S.empty() || a[i] >= a[S.top()]) {
65             r2[i] = i;
66             S.push(i);
67         }
68         else {
69             while (!S.empty() && a[S.top()] > a[i]) {
70                 r2[i] = r2[S.top()];
71                 S.pop();
72             }
73             S.push(i);
74         }
75     }while (!S.empty()) S.pop();
76     for (i = 1;i <= N;++i)
77     {
78         mint[i] += (-l2[i]+r2[i])+(i-l2[i])*(r2[i]-i);
79     }
80     LL ans = 0;
81     for (i = 1;i <= N;++i)
82     {
83         ans += (LL)a[i] * (maxt[i]-mint[i]);
84     }
85     printf("%lld\n", ans);
86     return 0;
87 }

迭代:

 1 #include <iostream>
 2 #include<algorithm>
 3 #include<stack>
 4 #include<cstdio>
 5 using namespace std;
 6 typedef long long LL;
 7 const int MAX = 50005;
 8 int a[MAX], l1[MAX], r1[MAX], l2[MAX], r2[MAX];
 9 int maxt[MAX], mint[MAX];
10 int main()
11 {
12     int N, i, j, k;
13     scanf("%d", &N);
14     for (i = 1;i <= N;++i) scanf("%d", a + i);
15     for (i = 1;i <= N;++i) {
16         l1[i] = r1[i] = i;
17         l2[i] = r2[i] = i;
18     }
19     for (i = 1;i <= N;++i) {
20         while (l1[i] != 1 && a[i] >= a[l1[i] - 1]) 
21             l1[i] = l1[l1[i]-1];
22         while (l2[i] != 1 && a[i] <= a[l2[i] - 1])
23             l2[i] = l2[l2[i] - 1];
24     }
25     for (i = N;i >= 1;--i) {
26         while (r1[i] != N&&a[i] > a[r1[i] + 1])
27             r1[i] = r1[r1[i] + 1];
28         while (r2[i] != N&&a[i] < a[r2[i] + 1])
29             r2[i] = r2[r2[i] + 1];
30     }
31     LL ans = 0;
32     for (i = 1;i <= N;++i) {
33         ans += (LL)a[i] * ((r1[i] - l1[i]) + (i - l1[i])*(r1[i] - i)- (-l2[i] + r2[i]) - (i - l2[i])*(r2[i] - i));
34     }
35     cout << ans << endl;
36     //system("pause");
37     return 0;
38 }

 

51nod 1215 单调栈/迭代

标签:枚举   ges   修改   tput   分享   red   计算   时空   group   

原文地址:http://www.cnblogs.com/zzqc/p/7413711.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!