P10173 「OICon-02」maxiMINImax (单调栈+树状数组)
首先观察所求的式子,我们可以很容易发现
此时如果要考虑枚举其中一个区间,我们肯定选择中间的
我们思考是否真的需要枚举区间。枚举区间的意义是能够知道
此时我们知道,只需要满足
考虑计算贡献,我们容易用单调栈预处理出每个位置作为最大值/最小值的区间数
此时枚举
如何维护这个东西?考虑拆开式子,发现只需要维护
我们在计算时要满足第一个条件,这里用一个技巧,就是把数从小到大放进去同时维护树状数组即可,当然也可以用权值线段树分别维护前缀和后缀。
复杂度
#include <bits/stdc++.h>
typedef long long i64;
#define pii std::pair<i64, i64>
#define fi first
#define se second
const int N = 1000010;
const int mod = 9712176;
i64 a[N], s[N];
i64 lmin[N], lmax[N], rmin[N], rmax[N], minn[N], maxn[N];
i64 n;
int lowbit(int x) {return x & (-x);}
struct bit {
i64 c[N];
void add(int x, i64 y) {
for(int i = x; i <= n; i += lowbit(i)) {
c[i] = (c[i] + y) % mod;
}
}
i64 qmax(int x) {
if(!x) return 0;
i64 ret = 0;
for(int i = x; i; i -= lowbit(i)) {
ret = (ret + c[i]) % mod;
}
return ret;
}
}t1, t2;
void Solve() {
std::cin >> n;
for(int i = 1; i <= n; i++) {
std::cin >> a[i];
}
int top = 0;
for(int i = 1; i <= n; i++) {
while(top && a[s[top]] >= a[i]) top--;
lmin[i] = s[top] + 1;
s[++top] = i;
}
top = 0;
for(int i = 1; i <= n; i++) {
while(top && a[s[top]] <= a[i]) top--;
lmax[i] = s[top] + 1;
s[++top] = i;
}
top = 0;
for(int i = n; i >= 1; i--) {
while(top && a[s[top]] >= a[i]) top--;
if(!top) rmin[i] = n;
else rmin[i] = s[top] - 1;
s[++top] = i;
}
top = 0;
for(int i = n; i >= 1; i--) {
while(top && a[s[top]] <= a[i]) top--;
if(!top) rmax[i] = n;
else rmax[i] = s[top] - 1;
s[++top] = i;
}
for(int i = 1; i <= n; i++) {
minn[i] = 1ll * (i - lmin[i] + 1) * (rmin[i] - i + 1) % mod;
maxn[i] = 1ll * (i - lmax[i] + 1) * (rmax[i] - i + 1) % mod;
}
std::vector<pii> b(n + 1);
for(int i = 1; i <= n; i++) {
b[i].fi = a[i], b[i].se = i;
}
std::sort(b.begin() + 1, b.end());
i64 ans = 0;
for(int i = 1; i <= n; i++) {
i64 dmx1 = t1.qmax(b[i].se - 1);
i64 dmx3 = (t1.qmax(n) - t1.qmax(b[i].se) + mod) % mod;
i64 dmx1mx1 = t2.qmax(b[i].se - 1);
i64 dmx3mx3 = (t2.qmax(n) - t2.qmax(b[i].se) + mod) % mod;
// std::cout << dmx1 << " " << dmx3 << " " << dmx1mx1 << " " << dmx3mx3 << "\n";
ans = (ans + b[i].fi * b[i].fi % mod * dmx1 % mod * dmx3 % mod * minn[b[i].se] % mod) % mod;
ans = (ans - b[i].fi * dmx3mx3 % mod * dmx1 % mod * minn[b[i].se] % mod + mod) % mod;
ans = (ans - b[i].fi * dmx1mx1 % mod * dmx3 % mod * minn[b[i].se] % mod + mod) % mod;
ans = (ans + dmx1mx1 * dmx3mx3 % mod * minn[b[i].se] % mod) % mod;
t1.add(b[i].se, maxn[b[i].se]);
t2.add(b[i].se, maxn[b[i].se] * b[i].fi % mod);
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
Solve();
return 0;
}
Buy me a cup of coffee ☕.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具