区区区间间间 思维+单调栈
思维
观察到这就离胜利不远了
知道a[i] 的 左扩展 l[i] 和 右扩展 r[i] 时,
则以a[i] 作为最大值的区间个数可以计算出来
两边的数组合,加 一个端点是i ,另一个端点在 l[i] ~ r[i]中。
注意l[i] 取 >= 时,r[i] 应取 < 才能保证不重不漏。
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define fi first
#define se second
#define pb push_back
#define foa(x, y, z) for(int x = (y), ooo = (z); x <= z; ++x)
#define fos(x, y, z) for(int x = (y), ooo = (z); x >= z; --x)
#define ckmax(x, y) ((x) < (y) ? (x) = (y), 1 : 0)
#define ckmin(x, y) ((x) > (y) ? (x) = (y), 1 : 0)
typedef pair<int, int> pii;
typedef long long ll;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
int n, m;
int a[N], l[N], r[N];
int calc()
{
vector<int> v;
a[0] = inf;
v.pb(0);
foa(i, 1, n) {
// l[i] = i;
while(v.size() && a[v.back()] <= a[i]) {
// l[i] = v.back();
v.pop_back();
}
l[i] = v.back() + 1;
v.pb(i);
}
v.clear();
a[n + 1] = inf;
v.pb(n + 1);
fos(i, n, 1) {
// r[i] = i;
while(v.size() && a[v.back()] < a[i]) {
// r[i] = v.back();
v.pop_back();
}
r[i] = v.back() - 1;
v.pb(i);
}
int res = 0;
foa(i, 1, n) res += a[i] * (r[i] - l[i] + (i - l[i]) * (r[i] - i));
// foa(i, 1, n) printf("--- %d %d %d\n", i, l[i], r[i]);
return res;
}
void solve()
{
cin >> n;
foa(i, 1, n) cin >> a[i];
int res = calc();
foa(i, 1, n) a[i] = -a[i];
res += calc();
cout << res << endl;
}
signed main()
{
// ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t;
cin >> t;
while(t--)
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」