[CF2065H] Bro Thinks He's Him 题解
首先,段数等于相邻不等的数量加一。
如:0011101101
中,有
有了这个转化,我们就可以拆贡献到每一组【相邻不等】上了。
我们计算一个下标
找到一个
所以
那修改怎么处理呢?
我们考虑一次修改会对答案产生哪些变动。
先考虑
对于
同理,翻转之后(
我们思考如何用数据结构优化这件事。
我们要做的事情就是维护
可以开两个线段树 tr[2]
(树状数组),这两个分别表示前缀中,tr[0]
单点减 tr[1]
单点加
算贡献变动就是将 tr[a[i]^1]
的前缀查询。
统一使用树状数组实现,后缀和的查询就是将下标关于
时间复杂度
#include <bits/stdc++.h>
using namespace std;
//#define filename "xxx"
#define FileOperations() freopen(filename".in", "r", stdin), freopen(filename".out", "w", stdout)
#define multi_cases 1
#define inf 0x3f3f3f3f
#define Linf 0x3f3f3f3f3f3f3f3f
#define pii pair<int, int>
#define all(v) v.begin(), v.end()
template<class T> bool vmax(T &a, T b) { return b > a ? a = b, true : false; }
template<class T> bool vmin(T &a, T b) { return b < a ? a = b, true : false; }
template<class T> void clear(T &x) { T().swap(x); }
#define int long long
const int N = 2e5+2, P = 998244353;
void reduce(int &a) { if(a >= P) a -= P; }
void enlarge(int &a) { if(a < 0) a += P; }
void vadd(int &a, int b) { a += b, reduce(a); }
void vsub(int &a, int b) { a -= b, enlarge(a); }
int pw[N];
char s[N];
int n, a[N];
struct BIT {
int n, c[N];
void init(int n = 0) {
this->n = n;
memset(c, 0, sizeof(int) * (n+1));
}
void add(int idx, int v) { for(; idx <= n; idx += idx & -idx) vadd(c[idx], v); }
int query(int idx) {
int res = 0;
for(; idx; idx -= idx & -idx) vadd(res, c[idx]);
return res;
}
} pretr[2], suftr[2];
int calc() {
int ans = pw[n] - 1, c[2] = { };
for(int i = 1; i <= n; ++i) {
vadd(ans, c[a[i] ^ 1] * pw[n-i] % P);
vadd(c[a[i]], pw[i-1]);
}
return ans;
}
void Traveller() {
scanf("%s", s+1);
n = strlen(s+1);
for(int i = 1; i <= n; ++i) a[i] = s[i] ^ 48;
pw[0] = 1;
for(int i = 1; i <= n; ++i) reduce(pw[i] = pw[i-1] << 1);
pretr[0].init(n), pretr[1].init(n);
for(int i = 1; i <= n; ++i) pretr[a[i]].add(i, pw[i-1]);
suftr[0].init(n), suftr[1].init(n);
for(int i = 1; i <= n; ++i) suftr[a[i]].add(n-i+1, pw[n-i]);
int ans = calc(), q;
scanf("%lld", &q);
for(int i = 1, p; i <= q; ++i) {
scanf("%lld", &p);
vsub(ans, pw[n-p] * pretr[a[p] ^ 1].query(p) % P);
pretr[a[p]].add(p, -pw[p-1] + P);
vsub(ans, pw[p-1] * suftr[a[p] ^ 1].query(n-p+1) % P);
suftr[a[p]].add(n-p+1, -pw[n-p] + P);
a[p] ^= 1;
vadd(ans, pw[n-p] * pretr[a[p] ^ 1].query(p) % P);
pretr[a[p]].add(p, pw[p-1]);
vadd(ans, pw[p-1] * suftr[a[p] ^ 1].query(n-p+1) % P);
suftr[a[p]].add(n-p+1, pw[n-p]);
printf("%lld ", ans);
}
puts("");
}
signed main() {
#ifdef filename
FileOperations();
#endif
signed _ = 1;
#ifdef multi_cases
scanf("%d", &_);
#endif
while(_--) Traveller();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步