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';
}