CF817D Imbalanced Array&P6503 [COCI2010-2011#3] DIFERENCIJA&SP10622 DIFERENC - DIFERENCIJA 做题笔记

给出 $a_i(1\le i\le n\le 10^6)$,求$$ \sum_{i=1}^{n}\sum_{j=i}^{n}(\max_{i\le k\le j}\{a_k\}-\min_{i\le l\le j}\{a_l\}) $$

解法

化简:$$ \sum_{i=1}^{n}\sum_{j=i}^{n}\max\{a_k\}- \sum_{i=1}^{n}\sum_{j=i}^{n}\min\{a_l\} $$ 分别求值。

先处理每个区间的最大值(上面公式的前半部分)。 假设当前 $a_i$ 是某个区间 $(l,r)$ 的最大值,那么可以贪心地得到当区间长度 $r-l-1$ 最大时,$a_r\ge a_i,a_l\ge a_i$。因为如果包含 $l,r$ 那么 $a_i$ 就不是区间最大了。

最小值同理。

于是问题转换成求每个 $a_i$ 向前和向后分别求出第一个比 $a_i$ 大的数和第一个比 $a_i$ 小的数。

用单调栈扫两遍解决。

注意栈空时的特判。

代码

#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int N=1145141;
int a[N],pma[N],sma[N],pmi[N],smi[N];
ll suma,sumi;
int main()
{
int n;
scanf("%d",&n);
vector<int> ma,mi;
for(int i=1;i<=n;i++)
{
scanf("%d",a+i);
}
for(int i=1;i<=n;i++)
{
while(!ma.empty()&&a[ma.back()]<a[i])
{
ma.pop_back();
}
if(ma.empty())// 特判后赋值,下同
{
pma[i]=0;
}
else
{
pma[i]=ma.back();
}
ma.push_back(i);
while(!mi.empty()&&a[mi.back()]>a[i])
{
mi.pop_back();
}
if(mi.empty())
{
pmi[i]=0;
}
else
{
pmi[i]=mi.back();
}
mi.push_back(i);
}
mi.clear();
ma.clear();
for(int i=n;i>0;i--)
{
while(!ma.empty()&&a[ma.back()]<=a[i])
{
ma.pop_back();
}
if(ma.empty())
{
sma[i]=n+1;
}
else
{
sma[i]=ma.back();
}
ma.push_back(i);
while(!mi.empty()&&a[mi.back()]>=a[i])
{
mi.pop_back();
}
if(mi.empty())
{
smi[i]=n+1;
}
else
{
smi[i]=mi.back();
}
mi.push_back(i);
}
for(int i=1;i<=n;i++)
{
suma+=(a[i]*(i-pma[i])*(sma[i]-i));
sumi+=(a[i]*(i-pmi[i])*(smi[i]-i));
}
printf("%lld",suma-sumi);
return 0;
}
posted @   Po7ed  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示