洛谷P6503[COCI2010-2011#3] DIFERENCIJA
[COCI2010-2011#3] DIFERENCIJA
题目描述
给出一个长度为 nnn 的序列 aia_iai,求出下列式子的值:
∑i=1n∑j=inmaxi≤k≤jak−mini≤k≤jak\sum_{i=1}^{n} \sum_{j=i}^{n} \max_{i\le k\le j} a_k-\min_{i\le k\le j} a_ki=1∑nj=i∑ni≤k≤jmaxak−i≤k≤jminak
即定义一个子序列的权值为序列内最大值与最小值的差。求出所有连续子序列的权值和。
输入格式
输入第一行一个整数 nnn,表示序列的长度。
接下来的 nnn 行,每行一个整数 aia_iai,描述这个序列。
输出格式
输出一行一个整数,表示式子的答案。
样例 #1
样例输入 #1
3
1
2
3
样例输出 #1
4
样例 #2
样例输入 #2
4
7
5
7
5
样例输出 #2
12
样例 #3
样例输入 #3
4
3
1
7
2
样例输出 #3
31
提示
数据规模与约定
对于 100%100\%100% 的数据,保证 2≤n≤3×1052\le n\le 3\times 10^52≤n≤3×105,1≤ai≤1081\le a_i\le 10^81≤ai≤108。
说明
题目译自 COCI2010-2011 CONTEST #3 T5 DIFERENCIJA。
偷偷打开标签
单调队列\colorbox{darkblue}{\color{darkblue}\boxed{\begin{gathered}\begin{gathered}\small \color{white}{\text{ 单调队列}}\end{gathered}\cr\end{gathered}}} 单调队列栈\colorbox{darkblue}{\color{darkblue}\boxed{\begin{gathered}\begin{gathered}\small \color{white}{\text{ 栈}}\end{gathered}\cr\end{gathered}}} 栈COCI\colorbox{skyblue}{\color{skyblue}\boxed{\begin{gathered}\begin{gathered}\small \color{white}{\text{ COCI}}\end{gathered}\cr\end{gathered}}} COCIO2优化\colorbox{orange}{\color{orange}\boxed{\begin{gathered}\begin{gathered}\small \color{white}{\text{ O2优化}}\end{gathered}\cr\end{gathered}}} O2优化2010\colorbox{blue}{\color{blue}\boxed{\begin{gathered}\begin{gathered}\small \color{white}{\text{ 2010}}\end{gathered}\cr\end{gathered}}} 2010
那么,我们从哪方面入手?
How about 单调队列?
似乎麻烦,我不干
那栈呢
就试试看吧
先把他当最大的,然后最小
最大左边缘lmx 最大右边缘 rmx 最小左边缘 lmn 最小右边缘 rmn
然鹅,有一个大问题,画个图就知道
7 4 5 3 7
7-------》
《------7
有没有发现,两个7行走的路线有重复?
于是呢,我便发明了个好方法,就是左(右)区间可以右等于的,另一边不行
然后呢,样例没过
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[300007];
struct pd{int lmx,rmx,lmn,rmn;
}k[300007];
struct _stack_{int a[1000007],n;void push(int x){a[++n]=x;return;}void pop(){--n;return;}void clear(){n=0;}bool empty(){return (n==0);};int size(){return n;}int top(){return a[n];}
};
_stack_ lmx,rmx,lmn,rmn;
int ans;
signed main(){scanf("%lld",&n);for(int i=1;i<=n;i++)scanf("%lld",a+i);for(int i=1;i<=n;i++){while(!lmx.empty()&&a[lmx.top()]<=a[i])lmx.pop();k[i].lmx=(!lmx.empty())?(lmx.top()):1;lmx.push(i);}for(int i=n;i>=1;i--){while(!rmx.empty()&&a[rmx.top()]<a[i])rmx.pop();k[i].rmx=(!rmx.empty())?(rmx.top()):n;rmx.push(i);}for(int i=1;i<=n;i++){while(!lmn.empty()&&a[lmn.top()]>=a[i])lmn.pop();k[i].lmn=(!lmn.empty())?(lmn.top()):1;lmn.push(i);}for(int i=n;i>=1;i--){while(!rmn.empty()&&a[rmn.top()]>a[i])rmn.pop();k[i].rmn=(!rmn.empty())?(rmn.top()):n;rmn.push(i);}for(int i=1;i<=n;i++){ans+=a[i]*((k[i].rmx-k[i].lmx+1)-(k[i].rmn-k[i].lmn+1));}printf("%lld",ans);return 0;
}
经过一番修改,我发现了如下的问题:
- 左右区间不合法的也判进去了
- 少了很多区间
修改后的样子:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[300007];
struct pd{int lmx,rmx,lmn,rmn;
}k[300007];
struct _stack_{//手写栈int a[1000007],n;void push(int x){a[++n]=x;return;}void pop(){--n;return;}void clear(){n=0;}bool empty(){return (n==0);};int size(){return n;}int top(){return a[n];}
};
_stack_ lmx,rmx,lmn,rmn;
int ans;
signed main(){scanf("%lld",&n);for(int i=1;i<=n;i++)scanf("%lld",a+i);for(int i=1;i<=n;i++){while(!lmx.empty()&&a[lmx.top()]<=a[i])lmx.pop();k[i].lmx=(!lmx.empty())?(lmx.top()+1):1;lmx.push(i);}for(int i=n;i>=1;i--){while(!rmx.empty()&&a[rmx.top()]<a[i])rmx.pop();k[i].rmx=(!rmx.empty())?(rmx.top()-1):n;rmx.push(i);}for(int i=1;i<=n;i++){while(!lmn.empty()&&a[lmn.top()]>=a[i])lmn.pop();k[i].lmn=(!lmn.empty())?(lmn.top()+1):1;lmn.push(i);}for(int i=n;i>=1;i--){while(!rmn.empty()&&a[rmn.top()]>a[i])rmn.pop();k[i].rmn=(!rmn.empty())?(rmn.top()-1):n;rmn.push(i);}for(int i=1;i<=n;i++){ans+=a[i]*((k[i].rmx-i+1)*(i-k[i].lmx+1)-(k[i].rmn-i+1)*(i-k[i].lmn+1));}printf("%lld",ans);return 0;
}
完美AC\colorbox{green}{\color{green}\boxed{\begin{gathered}\begin{gathered}\small \color{white}{\text{ AC}}\end{gathered}\cr\end{gathered}}} AC
洛谷P6503[COCI2010-2011#3] DIFERENCIJA相关推荐
- 洛谷 P1873 [COCI 2011/2012 #5] EKO / 砍树
题目传送门: 洛谷 P1873 [COCI 2011/2012 #5] EKO / 砍树 题目描述 伐木工人 Mirko 需要砍 M 米长的木材.对 Mirko 来说这是很简单的工作,因为他有一个漂亮 ...
- 洛谷P1873 [COCI 2011/2012 #5] EKO / 砍树(二分法)
题目链接 : 洛谷P1873 [COCI 2011/2012 #5] EKO / 砍树 文章目录 前言 一.题目 题目描述 输入格式 输出格式 输入输出样例 说明/提示 二.代码 前言 第一次写博客, ...
- 【C++】洛谷P1873 [COCI 2011/2012 #5] EKO / 砍树
[COCI 2011/2012 #5] EKO / 砍树 题目描述 伐木工人 Mirko 需要砍 MMM 米长的木材.对 Mirko 来说这是很简单的工作,因为他有一个漂亮的新伐木机,可以如野火一般砍 ...
- 洛谷 P1873 [COCI 2011/2012 #5] EKO / 砍树 二分
# [COCI 2011/2012 #5] EKO / 砍树 ## 题目描述 伐木工人 Mirko 需要砍 $M$ 米长的木材.对 Mirko 来说这是很简单的工作,因为他有一个漂亮的新伐木机,可以如 ...
- 洛谷P1873 [COCI 2011/2012 #5] EKO / 砍树
题目描述 伐木工人 Mirko 需要砍 MM 米长的木材.对 Mirko 来说这是很简单的工作,因为他有一个漂亮的新伐木机,可以如野火一般砍伐森林.不过,Mirko 只被允许砍伐一排树. Mirko ...
- 洛谷P1130 红牌 动态规划
洛谷P1130 红牌 动态规划 状态转移方程 dp[ j ][ i ] = dp[ j-1 ][ i-1 ] + dp[ j ][ i-1 ] 然后 1 的时候判一下就行 1 #include ...
- (差分)洛谷P4231 三步必杀
洛谷P4231 三步必杀 三步必杀 题目背景 (三)旧都 离开狭窄的洞穴,眼前豁然开朗. 天空飘着不寻常的雪花. 一反之前的幽闭,现在面对的,是繁华的街市,可以听见酒碗碰撞的声音. 这是由被人们厌恶的 ...
- (树状数组+逆元)洛谷P5142 区间方差
洛谷P5142 区间方差 (^ w ^) 题目背景 出题人并没有能力写有趣的题面-- 题目描述 对于一个长度为n的序列a1,a2,a3⋯ana_1,a_2,a_3\cdots a_na1,a2,a ...
- 洛谷 P7960 [NOIP2021] 报数
PS:如果读过题了可以跳过题目描述直接到题解部分 提交链接:洛谷 P7960 [NOIP2021] 报数 题目 题目描述 报数游戏是一个广为流传的休闲小游戏.参加游戏的每个人要按一定顺序轮流报数,但如 ...
最新文章
- TableView的集合
- 给标签定义通用样式的css文件
- gitee最多上传多大文件_H5移动端图片压缩上传,基于Jquery的前端,实现拍照上传,选择相册
- ARM(IMX6U)裸机模仿STM32驱动开发实验(定义外设结构体)
- SqlServer三种常用窗口函数
- Windows应用程序进阶2(非模态对话框 通用对话框)
- 利用CSS3中的clac()实现按照屏幕分辨率自适应宽度
- 天马行空脚踏实地,阿里巴巴有群百里挑一的天才应届生...
- 如何制作朋友圈搞笑证件图片(附源码实例)
- 【C语言典例】——day8:猜名次
- 七大云架构设计在线绘图工具
- python笔记003
- python设计迷宫_用Python制作迷宫GIF
- 对象不可达,一定会被垃圾收集器回收么?
- android OTG (USB读写,U盘读写)最全使用相关总结
- 2年Java软件工程师的觉悟
- Linux操作系统的基础知识
- ant design pro 菜单图标引入问题 iconfontUrl inconfont图标本地
- 分享snopt优化工具箱matlab版
- Martian分析:轻量级微服务网络框架试用(Mars)