1
希望对你有帮助.|

zouyua

园龄:1年9个月粉丝:3关注:3

信息工程大学第五届超越杯程序设计竞赛(同步赛)A遗失的旋律

题目链接 :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;
}
复制代码

 

本文作者:zouyua

本文链接:https://www.cnblogs.com/ZouYua/p/18107461

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   zouyua  阅读(16)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起