ARC169F Large DP Table
从小往大考虑,取出当前 \(A\) 或 \(B\) 最小的行,不妨设为 \(p\) 行。
那么 \(\ge p\) 的行的路径都是先到 \(p\),然后往左走到 \((p,1)\),然后再往上。不难发现此时 \(<p\) 行和 \(\ge p\) 行独立。
假设当前我们计算了若干行列,平面被分成若干块。加入 \(p\) 行时只要考虑当前 \(p\) 穿过的所有子矩形。即考虑每个确定列 \(c\),贡献即为 \((nxt_c-c)(nxt_p-p)(p-prv_p)\)。容易维护做到 1log 或线性。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int> ;
const int mod = 998244353;
void Add(int &x, ll y) { x = (x + y) % mod; }
int Pow(int x, int y) {
int b = x, r = 1;
for(; y; b = (ll)b * b % mod, y /= 2) {
if(y & 1) r = (ll)r * b % mod;
}
return r;
}
const int kN = 2.5e5 + 5;
int n;
int a[2][kN], v[2][kN];
pii pos[kN * 2];
int main() {
// freopen("1.in", "r", stdin);
// freopen("1.out", "w", stdout);
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for(int i : {0, 1}) {
for(int j = 1; j <= n; j++) {
cin >> a[i][j];
pos[a[i][j]] = pii {i, j};
}
}
for(int i : {0, 1}) {
for(int j = 1; j <= n; j++) cin >> v[i][j];
}
set<int> st[2];
st[0] = st[1] = set<int> {1, n + 1};
int sum[2] = {0, 0};
for(int o : {0, 1}) {
sum[o] = (ll)v[o][1] * n % mod;
}
int ans = 0;
for(int i = 3; i <= 2 * n; i++) {
auto [o, p] = pos[i];
auto it = st[o].insert(p).first;
int prv = *prev(it), nxt = *next(it);
Add(sum[o], (ll)v[o][prv] * (p + mod - nxt));
Add(sum[o], (ll)v[o][p] * (nxt - p));
Add(ans, (ll)sum[o ^ 1] * (*it - *prev(it)) % mod * (*next(it) - *it));
}
cout << ans << "\n";
return 0;
}
浙公网安备 33010602011771号