题解 P9400 「DBOI」Round 1 三班不一般
显然有这样一个想法,设
转移方程:
直接转移显然不行,但观察到
相当于在
此时已经可以使用平衡树或块状链表维护,注意到至多向前插入
时间复杂度
#include <bits/stdc++.h>
using namespace std;
typedef long long i64;
const int maxn = 200005, mod = 998244353;
int n, a, b;
int tre[maxn * 8], mul[maxn * 8], m, pl, pr; // pl, pr 维护 f 数组第二维对应线段树上的编号范围
int read()
{
int ret = 0, ch = getchar();
for (; !isdigit(ch); ch = getchar())
;
for (; isdigit(ch); ch = getchar())
ret = (ret << 3) + (ret << 1) + (ch & 15);
return ret;
}
void build(int root, int l, int r)
{
mul[root] = 1;
if (l < r)
{
int mid = l + r >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
}
}
void push_down(int root)
{
if (mul[root] != 1)
{
tre[root << 1] = (i64)tre[root << 1] * mul[root] % mod;
mul[root << 1] = (i64)mul[root << 1] * mul[root] % mod;
tre[root << 1 | 1] = (i64)tre[root << 1 | 1] * mul[root] % mod;
mul[root << 1 | 1] = (i64)mul[root << 1 | 1] * mul[root] % mod;
mul[root] = 1;
}
}
void modify(int root, int l, int r, int x, int v)
{
if (l == r)
{
tre[root] = v;
return;
}
int mid = l + r >> 1;
push_down(root);
if (x <= mid)
modify(root << 1, l, mid, x, v);
else
modify(root << 1 | 1, mid + 1, r, x, v);
tre[root] = (tre[root << 1] + tre[root << 1 | 1]) % mod;
}
void multiply(int root, int l, int r, int x, int y, int v)
{
if (x <= l && r <= y)
{
tre[root] = (i64)tre[root] * v % mod;
mul[root] = (i64)mul[root] * v % mod;
return;
}
int mid = l + r >> 1;
push_down(root);
if (x <= mid)
multiply(root << 1, l, mid, x, y, v);
if (mid < y)
multiply(root << 1 | 1, mid + 1, r, x, y, v);
tre[root] = (tre[root << 1] + tre[root << 1 | 1]) % mod;
}
int sum(int root, int l, int r, int x, int y)
{
if (l > y || r < x)
return 0;
if (x <= l && r <= y)
return tre[root];
int mid = l + r >> 1;
push_down(root);
return (sum(root << 1, l, mid, x, y) + sum(root << 1 | 1, mid + 1, r, x, y)) % mod;
}
int main()
{
n = read(), a = read() - 1, b = read();
m = n + a + 1, pr = n + a + 1, pl = n + 1;
build(1, 1, m);
modify(1, 1, m, pl, 1);
for (int i = 1; i <= n; ++i)
{
int l = read(), r = read();
if (l <= b)
modify(1, 1, m, pl - 1, (i64)(min(b, r) - l + 1) * sum(1, 1, m, pl, pr) % mod);
if (r > b)
multiply(1, 1, m, pl, pr, r - max(b, l - 1));
else
multiply(1, 1, m, pl, pr, 0); // 这里等价于区间修改为 0
--pl, --pr;
}
printf("%d\n", sum(1, 1, m, pl, pr));
return 0;
}
数据结构优化 dp 实锤了。