题目链接 :A-遗失的旋律_信息工程大学第五届超越杯程序设计竞赛(同步赛) (nowcoder.com)
本场比赛的数据都很水,导致很多题暴力都能过,(出题人背大锅, 说实话,如果数据不水, 这场感觉质量是很高的
这题一开始除了知道是线段树维护0,1个数,确实没什么很清楚的思路,后来看榜一大堆人都过了, 就离谱,就蒙个暴力过去了
考虑一般规律((x + 1) * 2 + 1)* 2 + 1 可以拆解为(x * 2 + 1) * 2 + 1 + (1 * 2) + 1 * 2 + 1, 设一个节点的信息为cnt0, cn1表示0,1 的贡献
对于push_up操作
这个点的0的贡献也就是+1的贡献, 就是 左边的贡献 * 右边2的幂 + 右边0的的个数 即 cnt0[u] = cnt0[u << 1] * pw[cnt1[u << 1 | 1] ] + cnt0[u << 1 | 1]
这个点的1的贡献只用算1数量的幂,即1的个数 cnt1[u] = cnt1[u << 1] + cnt1[u << 1 | 1]
对于操作2 把x看作一个加数答案就是两个加数的贡献之和, 先把区间的答统计出来,返回pair类型, 答案即 x * pw[res.second] + res.first 记得每步取模
ac代码
#include<bits/stdc++.h> #define int long long using namespace std; using ull = unsigned long long; using ll = long long; using PII = pair<ll,ll>; using PIII = pair<ll, pair<ll,ll>>; #define endl "\n" #define pb push_back #define IOS ios::sync_with_stdio(false);cin.tie(0) #define lowbit(x) (x) & (-x) #define point(x) setiosflags(ios::fixed)<<setprecision(x) const int N=1e6+10; const int INF=0x3f3f3f3f; const int mod=998244353; string s; int n, m; int a[N], pw[N]; int cnt0[N], cnt1[N];//0字符的贡献, 1字符的贡献 void push_up(int u) { cnt0[u] = (cnt0[u << 1] * pw[cnt1[u << 1 | 1]] % mod + cnt0[u << 1 | 1]) % mod; cnt1[u] = cnt1[u << 1] + cnt1[u << 1 | 1]; } void build(int u, int l, int r) { if(l == r) { if(a[l] == 0) cnt0[u] = 1; else cnt1[u] = 1; return ; } int mid = l + r >> 1; build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r); push_up(u); } void update(int u, int l, int r, int pos, int k) { if(l == pos && r == pos) { cnt0[u] = 0, cnt1[u] = 0; if(k == 0) cnt0[u] = 1; else cnt1[u] = 1; return ; } int mid = l + r >> 1; if(pos <= mid) update(u << 1, l, mid, pos, k); else update(u << 1 | 1, mid + 1, r, pos, k); push_up(u); } PII query(int u, int l, int r, int x, int y) { //if(y < l || x > r) return {0, 0}; if( x <= l && r <= y) { return {cnt0[u], cnt1[u]}; } PII res1 = {0, 0}, res2 = {0, 0}, ans = {0, 0}; int mid = l + r >> 1; if(x <= mid) res1 = query(u << 1, l, mid, x, y); if(mid < y) res2 = query(u << 1 | 1, mid + 1, r, x, y); ans.first = (res1.first * pw[res2.second] % mod + res2.first) % mod; ans.second = res1.second + res2.second; return ans; } void solve(){ cin >> n >> m; cin >> s; s = " " + s; for(int i = 1; i <= n; i ++) a[i] = s[i] - '0'; pw[0] = 1; for(int i = 1; i < N; i++) pw[i] = (pw[i - 1] * 2) % mod; build(1,1, n); while(m --) { int op, l, r, x, y; cin >> op; if(op == 1) { cin >> y; a[y] ^= 1; update(1, 1, n, y, a[y]); } else { cin >> x >> l >> r; PII res = query(1, 1, n, l, r); cout << (res.first + (x * pw[res.second]) % mod) % mod << endl; } } //for(int i = 1; i <= n; i ++) cout << a[i] << " \n"[i == n]; } signed main() { IOS; int T=1; while(T--){ solve(); } return 0; }
标签:cnt0,信息工程,cin,long,贡献,遗失,using,程序设计,define From: https://www.cnblogs.com/ZouYua/p/18107461