zoukankan      html  css  js  c++  java
  • 牛客网 223C 区区区间间间(单调栈)

    题目链接:区区区间间间

    题意:给出长度为n的数字序列ai,定义区间(l,r)的价值为

    请你计算出

    题解:单调栈求ai左边和右边第一个比它小的位置,需要减去ai的个数为$(R_i-i+1)*(i-L_i+1)-1$。同理再用单调栈求ai左边和右边第一个比它大的位置,加上需要加上的ai个数即可。

    解释1:需要减去的ai个数为$(R_i-i+1)*(i-L_i+1)-1$。

    举个例子:1 2 3 4 5,求必须包含3的区间个数,左边有3种选择:1 2;2;不选;,右边也有三种选择:4 5;4;不选;但是题目中要求区间长度至少为2,所以两边都不选的情况不能计算在内。

    解释2:为什么单调栈中一个a[i]<=a[st.top()],另一个是a[i]<a[st.top()](>=和>也同理)。

    举个例子:5 6 5。这种情况很明显只有三个区间[5 6],[5 6 5],[6 5],即减去15。

    但是如果直接用<=,那么每个位置对应的区间(li,ri)分别为[1,3],[2,2],[1,3]。减去20。可以发现[1,3]区间被减了两次,所以需要保证相等的时候一端扩展,避免重复计算。

    stack:

     1 #include <stack>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 const int N=1e5+10;
     9 typedef long long ll;
    10 stack <int> st;
    11 ll l[N],r[N],a[N];
    12 
    13 int main(){
    14     int t;
    15     scanf("%d",&t);
    16 
    17     while(t--){
    18         int n;
    19         ll sum=0;
    20         scanf("%d",&n);
    21         for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    22         for(int i=1;i<=n;i++){
    23             while(st.size()&&a[i]<=a[st.top()]) st.pop();
    24             l[i]=st.size()==0?1:st.top()+1;
    25             st.push(i);
    26         }
    27         while(st.size()) st.pop();
    28         for(int i=n;i>=1;i--){
    29             while(st.size()&&a[i]<a[st.top()]) st.pop();
    30             r[i]=st.size()==0?n:st.top()-1;
    31             st.push(i);
    32         }
    33         while(st.size()) st.pop();
    34         for(int i=1;i<=n;i++) sum-=((r[i]-i+1)*(i-l[i]+1)-1)*a[i];
    35         for(int i=1;i<=n;i++){
    36             while(st.size()&&a[i]>=a[st.top()]) st.pop();
    37             l[i]=st.size()==0?1:st.top()+1;
    38             st.push(i);
    39         }
    40         while(st.size()) st.pop();
    41         for(int i=n;i>=1;i--){
    42             while(st.size()&&a[i]>a[st.top()]) st.pop();
    43             r[i]=st.size()==0?n:st.top()-1;
    44             st.push(i);
    45         }
    46         while(st.size()) st.pop();
    47         for(int i=1;i<=n;i++) sum+=((r[i]-i+1)*(i-l[i]+1)-1)*a[i];
    48         printf("%lld
    ",sum);
    49     }
    50 
    51     return 0;
    52 }
    View Code
  • 相关阅读:
    网络基础知识:(一)网络分层和网络设备
    Hadoop集群的JobHistoryServer详解(转载)
    Hive 多分隔符的使用 (转载)
    linux下用iptables做本机端口转发方法(转载)
    Linux 学习笔记
    MySQL时间差返回月个数
    hive下UDF函数的使用
    hive分区(partition)
    hive导出查询文件到本地文件的2种办法
    000_Tomcat 部署配置
  • 原文地址:https://www.cnblogs.com/pavtlly/p/10003420.html
Copyright © 2011-2022 走看看