zoukankan      html  css  js  c++  java
  • TOJ 4244: Sum

    4244: Sum 分享至QQ空间 去爱问答提问或回答

    Time Limit(Common/Java):3000MS/9000MS     Memory Limit:65536KByte
    Total Submit: 63            Accepted:10

    Description

     

    Given a sequence, we define the seqence's value equals the difference between the largest element and the smallest element in the sequence. As an example, the value of sequence (3, 1, 7, 2) = 7-1 = 6.

    Now, given a sequence S, output the sum of all value of consecutive subsequences.

    Input

     

    The first line has an integer N (2 ≤ N ≤ 300000) indicating the number of elements of the sequence. Then follows N lines, each line has a positive integer no larger than 10indicating an element of the sequence.

    Output

     

    Output the requested sum.

    Sample Input

    4
    3
    1
    7
    2

    Sample Output

     31

    Hint

    The consecutive subsequence of the sequence (3, 1, 7, 2) has:
    (3, 1), (1, 7), (7, 2), (3, 1, 7), (1, 7, 2), (3, 1, 7, 2)

    The sum of all values equals 2+6+5+6+6+6=31

    这题看起来很简单啊,然后自然而然就想到了朴素的O(n^2)做法,然而TLE,仔细一想要不用dp做,保存当前最大值,可是不还是O(n^2),虽然循环次数少点,堆排序TLE同理。那天坐CF做完了无聊了就又在想这道题,想不出来就在群里问了问,大神给了我单调栈的做法和sort排序找位置的方法

    sort大法来自010大神 点我获得代码

    我的单调栈就是向左向右找到其可以左延伸右延伸的位置,排列组合就好了(左边包括他自己有n个,右侧包括他自己有m个,他的贡献就是(mn-1)个)

    然后最大值来一次,最小值来一次,over

    和普通的单调栈一样,这个的话就是检查扩展,可以扩展就去和前面那个值一个位置,其实求的就是最多扩展到哪里。一个值最多被访问两次,和单调栈一样都是2*n

    单调栈也是,访问这个值,进队,可能还要出队。虽然是for套while但是复杂度还是n

    #include <cstdio>
    const int N=300005;
    __int64 a[N];
    int L[N],R[N];
    int main() {
        int n;
        while(~scanf("%d",&n)) {
            for(int i=1; i<=n; i++) {
                scanf("%I64d",&a[i]);
                L[i]=i;
                R[i]=i;
            }
            a[0]=-1;
            a[n+1]=-1;
            for(int i = 1; i <= n; i++) {
                while(a[i] <= a[L[i] - 1])
                    L[i] = L[L[i] - 1];
            }
            for(int i = n; i >= 1; i--) {
                while(a[i]< a[R[i] + 1])
                    R[i] = R[R[i] + 1];
            }
            __int64 sum=0;
            for(int i = 1; i <= n; i++) {
                sum-=a[i]*(i-L[i]+1)*(R[i]-i+1);
            }
            a[0]=1<<30;
            a[n+1]=1<<30;
            for(int i=1; i<=n; i++) {
                L[i]=i;
                R[i]=i;
            }
            for(int i = 1; i <= n; i++) {
                while(a[i] >= a[L[i] - 1])
                    L[i] = L[L[i] - 1];
            }
            for(int i = n; i >= 1; i--) {
                while(a[i] > a[R[i] + 1])
                    R[i] = R[R[i] + 1];
            }
            for(int i = 1; i <= n; i++) {
                sum+=a[i]*(i-L[i]+1)*(R[i]-i+1);
            }
            printf("%I64d
    ",sum);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    C语言I博客作业03
    C语言I—2019秋作业02
    C语言I博客作业04
    C语言I博客作业02
    C语言I博客作业02
    C语言I博客作业04
    C语言I博客作业02
    C语言I博客作业02
    第一周作业
    C语言I博客作业04
  • 原文地址:https://www.cnblogs.com/BobHuang/p/6832480.html
Copyright © 2011-2022 走看看