P10764 [BalticOI 2024] Wall

更好的阅读体验

首先可以枚举一个位置的水量 \(w\),求 \(c_{w}\) 表示其方案数,答案为 \(\sum c_{w}\)。那么可以设 \(c_{i,j}\) 表示位置 \(i\) 水量 \(\ge j\) 的方案数,答案为 \(\sum c_{i,j}\)。一个位置 \(i\),墙高为 \(a_i\),要求其有至少 \(j\) 单位的水,那么左右的 \(\max h\) 必然都要 \(\ge a_i+j\)。考虑容斥,分别求出左边 \(\max h <a_{i}+j\),右边 \(\max h<a_{i}+j\) 和左右两边的 \(\max h<a_{i}+j\) 的方案数。

考虑一个位置对方案数的贡献,不妨设 \(a_{k}<b_{k},h=a_{i}+j\),若 \(h>b_{k}\),那么贡献为 \(\times 2\),若 \(a_k<h\le b_k\),那么贡献为 \(\times 1\),若 \(h\le a_k\),那么贡献为 \(\times 0\)。以单独求左边条件的方案数为例,我们从左到右扫描线,在维护时只需要维护后缀 \(\times 2\),记录前缀 \(\times 0\) 的最大限制即可,查询就查询后缀和。

对于两边都有限制的情况,每次就是消除 \(i\) 的限制。不妨先考虑所有限制,用线段树维护,扫描到 \(i\) 的时候撤销 \(i\) 的限制即可。

#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int N = 5e5 + 5, M = 40, mod = 1e9 + 7, inf = 1e9;

inline void add(int & x, int y) {x += y; if (x >= mod) x -= mod;}
inline void dec(int & x, int y) {x += mod - y; if (x >= mod) x -= mod;}
inline int pls(int x, int y) {x += y; if (x >= mod) x -= mod; return x;}
inline int sub(int x, int y) {x += mod - y; if (x >= mod) x -= mod; return x;}
inline int mul(int x, int y) {return 1ll * x * y % mod;}

int n, a[N], b[N], ans, rt, _2[N], iv, pl[N], sl[N];

namespace smt {
  int ls[N * M], rs[N * M], s[N * M], tag[N * M], cnt;
#define ls(p) ls[p]
#define rs(p) rs[p]

  inline void init() {for (int i = 1; i <= cnt; ++i) ls[i] = rs[i] = s[i] = tag[i] = 0; cnt = rt = 0;}

  inline int nnd(int len) {return cnt++, s[cnt] = len, tag[cnt] = 1, cnt;}

  inline void work(int k, int p) {tag[p] = mul(tag[p], k), s[p] = mul(s[p], k);}

  inline void psd(int l, int r, int p) {
    int mid = (l + r) >> 1;
    if (!ls(p)) ls(p) = nnd(mid - l + 1);
    if (tag[p] ^ 1) work(tag[p], ls(p));
    if (!rs(p)) rs(p) = nnd(r - mid);
    if (tag[p] ^ 1) work(tag[p], rs(p));
    tag[p] = 1;
  }

  inline void psu(int p) {s[p] = pls(s[ls(p)], s[rs(p)]);}

  inline void ad(int l, int r, int L, int R, int k, int & p) {
    if (L > R) return;
    if (!p) p = nnd(r - l + 1);
    if (l >= L && r <= R) return work(k, p);
    int mid = (l + r) >> 1; psd(l, r, p);
    if (L <= mid) ad(l, mid, L, R, k, ls(p));
    if (R > mid) ad(mid + 1, r, L, R, k, rs(p));
    psu(p);
  }

  inline int ask(int l, int r, int L, int R, int p) {
    if (L > R) return 0;
    if (!p) return max(0, min(r, R) - max(l, L) + 1);
    if (l >= L && r <= R) return s[p];
    int mid = (l + r) >> 1, ans = 0; psd(l, r, p);
    if (L <= mid) add(ans, ask(l, mid, L, R, ls(p)));
    if (R > mid) add(ans, ask(mid + 1, r, L, R, rs(p)));
    return ans;
  }
}

using namespace smt;

inline int qpow(int a, int b) {
  int s = 1;
  while (b) {
    if (b & 1) s = mul(s, a);
    a = mul(a, a), b >>= 1;
  } return s;
}

signed main() {
  cin >> n;
  for (int i = 1; i <= n; ++i) cin >> a[i];
  for (int i = 1; i <= n; ++i) cin >> b[i];
  _2[0] = 1; for (int i = 1; i <= n; ++i) _2[i] = mul(_2[i - 1], 2);
  iv = qpow(2, mod - 2);
  init();
  for (int i = 1; i <= n; ++i) {
    add(ans, mul(inf - a[i], qpow(2, n - 1)));
    add(ans, mul(inf - b[i], qpow(2, n - 1)));
  }
  for (int i = 1, lm = 0; i <= n; ++i) {
    int t = ask(1, inf, max(lm + 1, a[i] + 1), inf, rt);
    dec(ans, mul(t, _2[n - i]));
    t = ask(1, inf, max(lm + 1, b[i] + 1), inf, rt);
    dec(ans, mul(t, _2[n - i]));
    ad(1, inf, max(a[i], b[i]) + 1, inf, 2, rt), lm = max(lm, min(a[i], b[i]));
    pl[i] = lm;
  }
  init();
  for (int i = n, lm = 0; i; --i) {
    int t = ask(1, inf, max(lm + 1, a[i] + 1), inf, rt);
    dec(ans, mul(t, _2[i - 1]));
    t = ask(1, inf, max(lm + 1, b[i] + 1), inf, rt);
    dec(ans, mul(t, _2[i - 1]));
    ad(1, inf, max(a[i], b[i]) + 1, inf, 2, rt), lm = max(lm, min(a[i], b[i]));
    sl[i] = lm;
  }
  init();
  for (int i = 1; i <= n; ++i) ad(1, inf, max(a[i], b[i]) + 1, inf, 2, rt);
  for (int i = 1; i <= n; ++i) {
    ad(1, inf, max(a[i], b[i]) + 1, inf, iv, rt);
    add(ans, ask(1, inf, max(max(pl[i - 1], sl[i + 1]), a[i]) + 1, inf, rt));
    add(ans, ask(1, inf, max(max(pl[i - 1], sl[i + 1]), b[i]) + 1, inf, rt));
    ad(1, inf, max(a[i], b[i]) + 1, inf, 2, rt);
  }
  cout << ans << endl;
  return 0;
}
posted @ 2024-11-05 21:25  Tagaki  阅读(41)  评论(0)    收藏  举报