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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具