AGC061C

AGC061C

首先考虑怎样不重不漏计数,注意到实际上直接 \(2^n\) 算重当且仅当存在一些区间,使得这个区间中实际上没有其他人。这样导出了一个 \(O(n^2)\) 的 dp,直接记录当前最严的限制即可。

然而小学生都知道一个技巧,叫做存在是不好做的,不存在是好做的。所以考虑容斥,钦定若干区间中没有其他人减去贡献。发现钦定一个区间后某个区间的人怎么选是确定的,发现这点需要我们读好这道题的标题。并且有这样一个性质就是说两个限制的区间是不交的才能合法。所以可以直接前缀和优化 dp。

const int N = 5e5 + 10;
int n, a[N], b[N];
int l[N], r[N];
int f[N], s[N], pw[N];

const int P = 998244353;
const int inv2 = (P + 1) / 2;

void add(int &x, int y) {
  (x += y) >= P ? x -= P : 0;
}
void sub(int &x, int y) {
  (x -= y) < 0 ? x += P : 0;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0), cout.tie(0);
  cin >> n;
  for(int i = 1; i <= n; ++i)
    cin >> a[i] >> b[i];
  for(int i = 1; i <= n; ++i) {
    l[i] = l[i - 1];
    while(b[l[i] + 1] < a[i]) ++l[i];
  }
  for(int i = 1; i <= n; ++i) {
    r[i] = r[i - 1];
    while(r[i] < n && a[r[i] + 1] < b[i]) ++ r[i];
  }
  int mul = 1;
  for(int i = 1; i <= n; ++i) 
    add(mul, mul);
  pw[0] = 1;
  for(int i = 1; i <= n; ++i)
    pw[i] = 1ll * pw[i - 1] * inv2 % P;
  f[0] = s[0] = 1;
  for(int i = 1; i <= n; ++i) {
    add(s[i], s[i - 1]);
    f[i] = 1ll * s[l[i]] * pw[r[i] - l[i]] % P;
    sub(s[r[i]], f[i]);
  }
  cout << 1ll * s[n] * mul % P << '\n';
}
posted @ 2024-01-12 16:41  DCH233  阅读(5)  评论(0编辑  收藏  举报