题解 CF1450H2 【Multithreading (Hard Version)】

回忆 H1 : (frac{1}{2^cnt} sumlimits_{i = 0, i equiv t pmod 2}^{cnt} |t - i| C_{cnt}^{i})

考虑把 (sumlimits_{i = 0, i equiv t pmod 2}^{cnt} |t - i| C_{cnt}^{i}) 拆开。

[sumlimits_{i = 0, i equiv t pmod 2}^{cnt} |t - i| C_{cnt}^{i} ]

[= sumlimits_{i = 0, i equiv t pmod 2}^{t} (t - i) C_{cnt}^{i} + sumlimits_{i = t + 2, i equiv t pmod 2}^{cnt} (i - t) C_{cnt}^{i} ]

[= t sumlimits_{i = 0, i equiv t pmod 2}^{t} C_{cnt}^i - sumlimits_{i = 0, i equiv t pmod 2}^{t} i C_{cnt}^i + sumlimits_{i = t + 2, i equiv t pmod 2}^{cnt} i C_{cnt}^{i} - tsumlimits_{i = t + 2, i equiv t pmod 2}^{cnt} C_{cnt}^{i} ]

因为 (i C_{cnt}^{i} = cnt C_{cnt - 1}^{i - 1})

[2 t sumlimits_{i = 0, i equiv tpmod 2}^{t} C_{cnt}^i - 2 cnt sumlimits_{i = 0, i equiv tpmod 2}^{t} C_{cnt - 1}^{i - 1} + cnt sumlimits_{i = 0, i equiv tpmod 2}^{cnt} C_{cnt - 1}^{i - 1} - tsumlimits_{i = 0, i equiv tpmod 2}^{cnt} C_{cnt}^{i} ]

因此我们只要能快速计算 (sumlimits_{i = 0, i equiv t pmod 2}^{t} C_{cnt}^i) 就可以快速得到答案。

[sumlimits_{i = 0, i equiv t pmod 2}^{t} C_{cnt}^i ]

[sumlimits_{i = 0, i equiv t pmod 2}^{t} C_{cnt - 1}^{i - 1} + C_{cnt - 1}^{i} ]

[sumlimits_{i = 0}^{t} C_{cnt - 1}^{i} ]

这个东西在 (cnt) 改变和在 (t) 改变时都可以快速计算。

主要是利用 (C_{x}^{i} = C_{x - 1}^i + C_{x - 1}^{i - 1})

注意 (t) 可能为负数。。。蒟蒻因为这个调了一个晚上。。。

#include<bits/stdc++.h>
#define L(i, j, k) for(int i = j, i##E = k; i <= i##E; i++) 
#define R(i, j, k) for(int i = j, i##E = k; i >= i##E; i--)
#define ll long long
#define ull unsigned long long 
#define db long double
#define pii pair<int, int>
#define mkp make_pair
using namespace std;
const int N = 2e5 + 7;
const int mod = 998244353;
const int inv2 = (mod + 1) / 2;
int qpow(int x, int y) {
	int res = 1;
	for(; y; x = 1ll * x * x % mod, y >>= 1) if(y & 1) res = 1ll * res * x % mod;
	return res;
}
int ny(int x) { return qpow(x, mod - 2); }
int jc[N], njc[N];
int C(int x, int y) { if(x < 0 || y < 0 || x < y) return 0; return 1ll * jc[x] * njc[y] % mod * njc[x - y] % mod; }
struct WORKER {
	int cnt, t, ans = 1;
	// 维护 sumlimits_{i = 0}^{t} C_{cnt}^{i}
	void cntup() { ans = (ans << 1) % mod, (ans += mod - C(cnt, t)) %= mod, ++cnt; if(cnt == 0) ans = (t >= 0); }
	void cntdown() { if(cnt == 0) ans = 0; --cnt, (ans += C(cnt, t)) %= mod, ans = 1ll * ans * inv2 % mod; }
	void tup() { (ans += C(cnt, t + 1)) %= mod, ++ t; }
	void tdown() { (ans += mod - C(cnt, t)) %= mod, -- t; }
} a, b, c, d;
int n, m, t, cnt, ans;
char s[N];
int getans() {
	int res = 0;
	if(cnt == 1) {
		L(i, 0, cnt) if((t + i) % 2 == 0) (res += 1ll * abs(t - i) * C(cnt, i) % mod) %= mod;
		res = 1ll * res * inv2 % mod;
		return res;
	}
	(res += 2ll * (t + mod) % mod * a.ans % mod) %= mod;
	(res += mod - 2ll * cnt * b.ans % mod) %= mod;
	(res += 1ll * cnt * c.ans % mod) %= mod;
	(res += mod - 1ll * (t + mod) % mod * d.ans % mod) %= mod;
	res = 1ll * res * qpow(inv2, cnt) % mod;
	return res;
}
void tup() { a.tup(), b.tup(), t++; }
void tdown() { a.tdown(), b.tdown(), t--; }
void cntup() { a.cntup(), b.cntup(), c.cntup(), d.cntup(), c.tup(), d.tup(), cnt++; }
void cntdown() { a.cntdown(), b.cntdown(), c.cntdown(), d.cntdown(), c.tdown(), d.tdown(), cnt--; }
int main() {
	scanf("%d%d", &n, &m);
	scanf("%s", s + 1);
	jc[0] = njc[0] = 1;
	L(i, 1, n) jc[i] = 1ll * jc[i - 1] * i % mod, njc[i] = ny(jc[i]);
	a.cntdown(), b.cntdown(), c.cntdown(), d.cntdown(), b.cntdown(), c.cntdown(), b.tdown(), c.tdown();
	L(i, 1, n) {
		if(s[i] == 'b') {
			if(i % 2) tdown();
			else tup();
		}
		else if(s[i] == '?') {
			cntup();
			if(i % 2 == 0) tup();
		}
	}
	printf("%d
", getans());
	while(m--) {
		int x; char opt[5]; scanf("%d%s", &x, opt + 1);
		if(opt[1] == 'b') {
			if(x % 2) tdown();
			else tup();
		}
		else if(opt[1] == '?') {
			cntup();
			if(x % 2 == 0) tup();
		}
		if(s[x] == 'b') {
			if(x % 2) tup();
			else tdown();
		}
		else if(s[x] == '?') {
			cntdown();
			if(x % 2 == 0) tdown();
		}
		s[x] = opt[1];
		printf("%d
", getans());
	}
	return 0;
}

祝大家学习愉快!

原文地址:https://www.cnblogs.com/zkyJuruo/p/14152445.html