【题解】Diferenc-Diferencija [SP10622]

传送门:\(\text{Diferenc-Diferencija}\) \(\text{[SP10622]}\)

【题目描述】

序列的值被定义成其中最大的元素减去最小的元素。如序列 \((3,1,7,2)\) 的值为 \(7-1=6\), 序列 \((42,42)\) 的值为 \(42-42=0\)。

现给定一长为 \(n\) 的序列 \(a\),求出所有连续子序列的值的和。

【样例】

样例输入:
3
1
2
3
样例输出:
4 样例输入:
4
7
5
7
5
样例输出:
12 样例输入:
4
3
1
7
2
样例输出:
31

【数据范围】

\(100 \%:\) \(2 \leqslant n \leqslant 3*10^5,\) \(1 \leqslant a[i] \leqslant 10^8\)


【分析】

先将子区间的右端点固定为 \(r\),此时一共有 \(r\) 个左端点 \((l \in [1,r])\) 可与之组成连续子序列,用 \(f_1[l]\) 表示 \(max \{a[j]\}(j \in [l,r])\) ,\(f_2[l]\) 表示 \(min \{a[j]\}(j \in [l,r])\) 。于是以 \(i\) 为右端点 \(r\) 的子区间贡献和为 \(\sum_{l=1}^{r} (f_1[l]-f_2[l])\),即 \(\sum_{l=1}^{r} f_1[l] - \sum_{l=1}^{r} f_2[l]\) 。我们可以分开算 \(f_1,f_2\) 的总和。

当右端点移至 \(r+1\) 时,需要用 \(a[r+1]\) 来更新 \(f_1,f_2\),可以直接扫描 \([1,r]\),但时间不过不了关。

随着 \(l\) 的减小,\(f_1[l]=max(a[l],f_1[l+1])\),可以发现 \(f_1[l]\) 是单调不下降的,同理 \(f_2[l]\) 单调不上升。

随着 \(r\) 的增大,\(f_1[l]=max(f_1[l],a[r+1])\),可以发现 \(f_1[l]\) 仍是单调不下降的,同理 \(f_2[l]\) 单调不上升。

然后我们就会发现一个现象:每次新加进来一个数 \(a[r+1]\) 时,它会将以 \(r+1\) 结尾的一段连续的区间 \(f_1[l],f_2[l](l \in [?,r+1])\) 全部赋值为 \(a[r+1]\),而且被覆盖掉的原数对这之后的区间不再有任何贡献。

于是我们可以用两个单调栈分别维护 \(f_1,f_2\),由于下标也是单调递增,所以可以将 \(f\) 值相同的合并起来,用 \(g\) 记录 \(f\) 相同的下标个数,另设一个变量 \(S\) 表示以 \(i\) 为右端点的贡献和,当加入新的 \(a[r]\) 时就不断弹走队尾直至保持单调时结束,同时更新 \(S\),最后累加答案即可。

【Code】

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define LL long long
#define Re register int
using namespace std;
const int N=3e5+2;
int n,t1,t2,a[N],f1[N],f2[N],g1[N],g2[N];LL S,ans;
inline void in(Re &x){
int f=0;x=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=f?-x:x;
}
int main(){
in(n);
for(Re i=1;i<=n;++i)in(a[i]);
f1[++t1]=a[1],f2[++t2]=a[1],g1[t1]=g2[t2]=1,ans=S=0;//初始化入队
for(Re i=2;i<=n;++i){
Re tmp=1;//f1[i]和f2[i]都一定会被覆盖,所以初始化为1
while(t1&&f1[t1]<=a[i])S-=(LL)f1[t1]*g1[t1],tmp+=g1[t1--];//更新最大值
f1[++t1]=a[i],g1[t1]=tmp,S+=(LL)a[i]*tmp;
tmp=1;
while(t2&&f2[t2]>=a[i])S+=(LL)f2[t2]*g2[t2],tmp+=g2[t2--];//更新最小值
f2[++t2]=a[i],g2[t2]=tmp,S-=(LL)a[i]*tmp;
ans+=S;//累加答案
}
printf("%lld\n",ans);
return 0;
}

【题解】Diferenc-Diferencija [SP10622]的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. MQ选型对比ActiveMQ,RabbitMQ,RocketMQ,Kafka 消息队列框架选哪个?

    最近研究消息队列,发现好几个框架,搜罗一下进行对比,说一下选型说明: 1)中小型软件公司,建议选RabbitMQ.一方面,erlang语言天生具备高并发的特性,而且他的管理界面用起来十分方便.不考虑r ...

  2. dos转unix

    方式一 # yum install dos2unix.x86_64 # dos2unix file 方式二 查看样式: :set ff? //dos/unix 设置: :set fileformat= ...

  3. 如何使用Postman发送get请求?

    一.接口测试介绍 接口测试:就是针对软件对外提供服务的接口输入输出进行测试,以及接口间相互逻辑的测试,验证接口功能和接口描述文档的一致性. 接口测试好处:接口测试通常能对系统测试的更为彻底,更高的保障 ...

  4. day 36

    目录 pymysql操作mysql 安装 连接 增 删 改 查 索引 为什么使用索引以及索引的作用 类比 索引的本质 索引的底层原理 索引的种类(重点) 主键索引 唯一索引 普通索引 索引的创建 主键 ...

  5. Linux中断管理 (3)workqueue工作队列【转】

    转自:https://www.cnblogs.com/arnoldlu/p/8659988.html 目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机 ...

  6. openstack 创建实例报错 **aborted: Failed to allocate the network(s), not rescheduling

    消息 Build of instance 6320b5f2-edc2-4e8e-b07c-0047f7ed8f6a aborted: Failed to allocate the network(s) ...

  7. Confluence 邮箱设置

    Confluence有两种方法设置邮箱 原理: confluence服务器配置好邮箱信息,用户触发邮件发送规则时,confluence服务使用已配置的邮箱信息登录到邮箱服务器,进行发件服务. 那么我们 ...

  8. AWS之EC2实例搭建LAMP服务器

    在 Amazon Linux 2 上安装 LAMP Web 服务器 创建EC2实例,在安全组添加HTTP(80)规则 步骤 1:准备 LAMP 服务器 1.使用putty连接到你的EC2实例上(AMI ...

  9. 201871010126 王亚涛 《面向对象程序设计(java)》 第6-7周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  10. uiautomator手动调试与快速高度设置

    创建java工程:Demo1包名:com.bing.cn类名:Test测试用例:testDemo android create uitest-project -n Demo1 -t 7 -p E:\e ...