• 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 <= 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
    ", 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 }
  • 相关阅读:
    使用uWSGI+Nginx+Supervisor部署管理Django应用程序
    Django REST framework使用ViewSets的自定义路由实现过程
    【转】nginx配置:location配置方法及实例详解
    Python模块的动态加载机制
    【转】Django中的request与response对象
    【转】Django Middleware
    【转】请求处理机制其三:view层与模板解析
    朝花夕拾
    买了台robosense的激光雷达,待开箱
    热力学量微分关系式总结+助记 Lebal:Research
  • 原文地址:https://www.cnblogs.com/zzqc/p/7413711.html
Copyright © 2020-2023  润新知