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;
}
posted @ 2026-09-08 08:58  CJzdc  阅读(6)  评论(0)    收藏  举报