Zbq's Music Challenge
题意:
一个长度为n的序列,每个位置可能是1或者0,1的概率是$p_i$。对于一个序列$S$,它的得分是
$$BasicScore=A\times \sum_{i=1}^{n}{S_i} \tag{1}$$
$$ combo(i)=\left\{ \begin{aligned} &S_i & &i=1 \\ &combo(i-1)+1 & &i\neq 1 ~\mathrm{and}~ S_i=1 \\ &combo(i-1)\times t & &\mathrm{otherwise} \end{aligned} \tag{2} \right.$$
$$ComboScore=B\times \sum_{i=1}^{n}{S_i\times combo(i)} \tag{3}$$
$$TotalScore=BasicScore+ComboScore \tag{4}$$
两种操作,修改每个位置的概率,询问一段区间得分的期望,答案对$998244353$取模。
分析:
分成两部分算,$BasicScore$可以对$p_i$求和得到。
对于每段区间,$f[i]$设第i位置数字期望是多少,那么$ComboScore = B \times \sum\limits_{i=l}^{r} p_i \times (f[i-1] + 1) $。
然后转移可以写成矩阵的形式。
$$ \left[ \begin{matrix} 1 & p_i & p_i \\ 0 & (1 - p_i) \times t + p_i & p_i\\ 0 & 0 & 1 \end{matrix} \right] \times \left[ \begin{matrix} sum\\ f[i - 1]\\ 1 \end{matrix} \right] = \left[ \begin{matrix} sum' \\ f[i]\\ 1 \end{matrix} \right] $$
于是,线段树维护一下即可。复杂度$O(nlogn \times 3^3)$
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cctype> #include<cmath> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> using namespace std; typedef long long LL; inline int read() {int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; }const int mod = 998244353; const int N = 500005; int p[N];int ksm(int a,int b) {int res = 1;while (b) {if (b & 1) res = 1ll * res * a % mod;a = 1ll * a * a % mod;b >>= 1;}return res; } int fen(int a,int b) { return 1ll * a * ksm(b, mod - 2) % mod; }int sum[N << 2], tt, NowAns, n, A, B; struct Mat{ int a[3][3]; Mat() { memset(a, 0, sizeof(a)); }void set(int p) {a[0][0] = 1;a[0][1] = a[0][2] = a[1][2] = p;a[1][1] = (1ll * (mod + 1 - p) % mod * tt % mod + p) % mod;a[2][2] = 1;} }T[N << 2]; Mat operator * (const Mat &A, const Mat &B) {Mat C;for (int k = 0; k < 3; ++k) for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) C.a[i][j] = (C.a[i][j] + 1ll * A.a[i][k] * B.a[k][j] % mod) % mod;return C; } inline void pushup(int rt) {T[rt] = T[rt << 1] * T[rt << 1 | 1]; sum[rt] = (sum[rt << 1] + sum[rt << 1 | 1]) % mod; } void build(int l,int r,int rt) {if (l == r) {T[rt].set(p[l]); sum[rt] = p[l]; return ; }int mid = (l + r) >> 1;build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1);pushup(rt); } void update(int l,int r,int rt,int pos) {if (l == r) {T[rt].set(p[l]); sum[rt] = p[l]; return ;}int mid = (l + r) >> 1;if (pos <= mid) update(l, mid, rt << 1, pos);else update(mid + 1, r, rt << 1 | 1, pos);pushup(rt); } Mat query(int l,int r,int rt,int L,int R) {if (L <= l && r <= R) { NowAns = (NowAns + sum[rt]) % mod; return T[rt]; }int mid = (l + r) >> 1;if (R <= mid) return query(l, mid, rt << 1, L, R);else if (L > mid) return query(mid + 1, r, rt << 1 | 1, L, R);else return query(l, mid, rt << 1, L, R) * query(mid + 1, r, rt << 1 | 1, L, R); } void query() {int x = read(), y = read();NowAns = 0;Mat now = query(1, n, 1, x, y);LL ans1 = NowAns, ans2 = now.a[0][2];cout << (1ll * ans1 * A % mod + 1ll * ans2 * B % mod) % mod << "\n"; } int main() {read();n = read();int Q = read(), ta = read(), tb = read();A = read(), B = read();tt = fen(ta, tb);for (int i = 1; i <= n; ++i) ta = read(), tb = read(), p[i] = fen(ta, tb);build(1, n, 1);while (Q --) {if (read()) query();else {int x = read(), ta = read(), tb = read(); p[x] = fen(ta, tb);update(1, n, 1, x); }}return 0; }