正の整数の所定のシーケンス\(A_1、\ A_2、\ \ cdots、\ A_N \)を探している、\ [\ displaystyle \ sum_ {I = 1} ^ n個の\ sum_ {J =} ^ N {(J-I + 1)\マックス[I、\の J] \分[I、\のJ]} \]
結果\(^ 9 10 \)モジュロ
\(N \ leq5 \ times10 ^ 5、\ a_iを\ [0、\ 10 ^ 8] \)
分割統治、CDQパーティション
間隔のために、パーティションを考える\([Lは、\ R] \) が見つかりました\(\最大\)ポイント\(POS \) 、\を([L、\ POS- 1]、\ [POS + 1、\ R&LT] \)再帰が、この効果的に対処しません\(\分\)の貢献をし、パーティションのCDQを考えます
現在の間隔の設定\([L、\ R&LT] \) 、再帰的プロセス(\ [\ R&LT、MID + 1] [L \中間]、\)\を、左端点算出\([L、\ミッドを] \) 、右端\([中間+ 1、\の R] \) 間隔を拠出
オーダー\(MX = \マックス[P、\ MID]、\のMn = \ [P、\ MID]分\) 。逆列挙エンドポイントを左(P \)\ので、(X \)\満足する\(MN \ GE \の分[ミッド+ 1、\ X] \)を最大\(X \)、\ (Y \)されている\(MX \ル\マックス[ミッド+ 1、\ Y] \) 最大\(Y \) 。仮定\(X <Y \) 、右端ポイント\(Q \)
- 場合(Q \当量X \)\、への貢献\(MXの\時間MN \倍 \ displaystyleの\和(Q-P + 1)\)
- (X <Q \当量のYの\ \)を、への貢献\(MXの\時間(\ displaystyleの \和((Q-P + 1)倍\ \分[X + 1、\ Q]))\)
- \(Y <Q \) 、への貢献\(\ displaystyleの\和(( Q-P + 1)\時間\分[X + 1、\ Q] \時間は最大[Y + 1、\ Q]を\ )\)
最初の直接のカウント
第二は、元の式に分割することができる\(MXの\時間(\ displaystyleの \和(q個の\時間\分[X + 1、\のQ]) - (I-1)\回\和\分[X + 1 、\ Q] \)
前記\(\ displaystyleの\和\分 [X + 1、\ Q] \) と\(\ displaystyleの\和(q個の \時間\分[X + 1、\ Q])\) 缶\(O(LEN) \)の前処理
同様に第三のオープンな括弧、\(\ displaystyleの\和(\分[X + 1、\ Q] \時間は最大[Y + 1、Q])\ \) および\(\ displaystyleの\和(Q \ 時間\分[X + 1、 \ qは】倍\ \マックス[Y + 1、\ Qを])\) することができるように\(\分[X + 1回\ \ q]は最高[Y + 1、\します\ Qは] \)に変換される\(1 \分[Xの+を、\ Q] \時間\マックス[X + 1、\ Q] \) 、することもできる\(O(LEN)\)の前処理
\(X \ GEのy \)状況と同じ方法
時間複雑\(O(N \ログN )\)
コード
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5 + 10, P = 1e9, inf = 1e8;
int n, ans, a[maxn], f1[maxn], f2[maxn], g1[maxn], g2[maxn], s1[maxn], s2[maxn];
inline void chkmax(int &x, int y) {
if (x < y) x = y;
}
inline void chkmin(int &x, int y) {
if (x > y) x = y;
}
inline int inc(int x, int y) {
x += y;
return x < P ? x : x - P;
}
inline int dec(int x, int y) {
x -= y;
return x < 0 ? x + P : x;
}
inline int mul(int x, int y) {
return 1ll * x * y % P;
}
inline int add(int &x, int y) {
x += y;
return x < P ? x : x -= P;
}
void cdq(int l, int r) {
if (l == r) {
add(ans, mul(a[l], a[l]));
return;
}
int mid = (l + r) >> 1;
cdq(l, mid), cdq(mid + 1, r);
f1[mid] = f2[mid] = g1[mid] = g2[mid] = s1[mid] = s2[mid] = 0;
for (int i = mid + 1, mx = 0, mn = inf; i <= r; i++) {
chkmax(mx, a[i]), chkmin(mn, a[i]);
f1[i] = inc(f1[i - 1], mx);
g1[i] = inc(g1[i - 1], mn);
f2[i] = inc(f2[i - 1], mul(mx, i));
g2[i] = inc(g2[i - 1], mul(mn, i));
s1[i] = inc(s1[i - 1], mul(mx, mn));
s2[i] = inc(s2[i - 1], mul(mul(mx, mn), i));
}
for (int i = mid, mx = 0, mn = inf, x = mid, y = mid; i >= l; i--) {
chkmax(mx, a[i]), chkmin(mn, a[i]);
while (x < r && a[x] >= mn && a[x + 1] >= mn) x++;
while (y < r && a[y] <= mx && a[y + 1] <= mx) y++;
int p = min(x, y), q = max(x, y);
add(ans, dec(dec(s2[r], s2[q]), mul(i - 1, dec(s1[r], s1[q]))));
add(ans, mul(mul(mx, mn), dec(1ll * (p - mid) * (p + mid + 1) / 2 % P, mul(i - 1, p - mid))));
if (x < y) {
add(ans, mul(mx, dec(dec(g2[y], g2[x]), mul(i - 1, dec(g1[y], g1[x])))));
} else {
add(ans, mul(mn, dec(dec(f2[x], f2[y]), mul(i - 1, dec(f1[x], f1[y])))));
}
}
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
}
cdq(1, n);
printf("%d", ans);
return 0;
}