zoukankan      html  css  js  c++  java
  • COCI. DIFERENCIJA(序列处理中的小技巧)


    DIFERENCIJA

    题目类型:虚拟题目 时间限制:1.0s 空间限制:64.0MB 提交文件大小限制:100.0KB 提示:%I64d & %I64u
    抓题完成
    序列的值被定义成其中最大的元素和最小的元素的中间的数的个数。如序列(3, 1, 7, 2) 的值为6, 序列(42, 42)的值为0.现给定一个序列,要求出所有连续子序列的值的和。
    输入:
    第一行一个整数 N (2 ≤ N ≤ 300 000), 表示序列的元素个数。
    接下来N行,每行一个正整数值不超过 100000 000.
    输出:
    一个数,表示所有子序列的值的和
    EXAMPLE TEST DATA
    input
    3
    1
    2
    3
    output
    4
     

    题目大意:

    给定一段序列,一段序列的权值是这段权值的最大值减去最小值,求每段序列的权值之和


    做法:

    Σimax-min 单调栈维护


    分析:
    可以知道最后答案是Σimax-min
    那么可以分开求得Σimax和Σmin

    如果我们有一个函数能求的序列的imax总和
    我们可以把序列全部取反,最小值边最大值
    可以同一个函数求得min总和

    我们可以考虑一个值是多少区间的最大值
    维护一个从大到小的单调栈
    前面的可以直接求得 第一个比他大的值的位置last

    last到i之间的序列就是a[i]为imax
    我们再考虑他右边第一个比他大的位置怎么求
    求得右边的长度,a[i]的个数就是左边*右边

    因为是左边个数*右边个数
    所以右边每加入一个 就会多一个左边个数

    这里有个技巧就是我们记一个累加和now

    表示我们记得是还没确定右边序列的点的左边序列长度之和

    这样我们就不用一次次地加,我们加在一起累加,复杂度就为n

    如果被弹出栈就减去对应的个数

    这样每次加now 就把左边所以应该加的一次次的加上了


    附上代码:
     
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=3e5+12;
    int n;
    int a[N];
    long long ans;
    int stack[N],temp;
    long long calc()
    {
        temp=1;
        long long now=0;
        long long sum=0;
        for(int i=1;i<=n;i++) 
        {
            while(temp>1&&a[stack[temp]]<a[i]) //维护一个从大到小的栈 
            {
                now-=1LL*(stack[temp]-stack[temp-1])*a[stack[temp]];//他不能再最为最大值值,右边不能再扩展了 
                temp--;
            }
            now+=1LL*(i-stack[temp])*a[i];//如果前面一个点没有被影响说明它比这个大 他会一直累加 
            sum+=now;//相当于加了左边的所有可以为当前最大值的个数 
            stack[++temp]=i;
        }
        return sum;
    }
    
    int main()
    {
        freopen("a.in","r",stdin);
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        ans+=calc();
        for(int i=1;i<=n;i++) a[i]=-a[i];
        ans+=calc();
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

  • 相关阅读:
    Linux I2C设备驱动编写(一)
    Device Tree常用方法解析
    Linux查看CPU型号及内存频率及其它信息的命令
    编译错误error: invalid storage class
    Mysql技术内幕——表&索引算法和锁
    mysql 锁
    MySQL 索引方式
    通过show status 来优化MySQL数据库
    linux shell 字符串操作(长度,查找,替换)详解
    bash中将字符串split成数组的方法
  • 原文地址:https://www.cnblogs.com/Heey/p/9028881.html
Copyright © 2011-2022 走看看