打卡信奥刷题(3390)用C++实现信奥题 P9883 [EC Final 2021] Fenwick Tree

P9883 [EC Final 2021] Fenwick Tree

题目描述

庞教授正在讲授关于 Fenwick 树(也称为二叉索引树)的课程。

在 Fenwick 树中,我们有一个长度为 nnn 的数组 c[1…n]c[1\ldots n]c[1n],初始时全为零(对于任何 1≤i≤n1\le i\le n1inc[i]=0c[i]=0c[i]=0)。每次,庞教授可以对某个位置 pospospos1≤pos≤n1\leq pos \leq n1posn)和一个值 valvalval 调用以下过程:

def update(pos, val):
    while (pos <= n):
        c[pos] += val
        pos += pos & (-pos)

注意,对于任何正整数 pospos & (-pos) 等于 pos 的最大 2 的幂。

在这个过程中,valvalval 可以是任意实数。在调用了若干次(零次或多次)后,庞教授忘记了数组 ccc 中的确切值。他只记得对于每个从 111nnniiic[i]c[i]c[i] 是否为零。庞教授想知道,在假设他的记忆是准确的情况下,他调用该过程的最小可能次数。

输入格式

第一行包含一个整数 T (1≤T≤105)T~(1 \le T \le 10^5)T (1T105),表示测试用例的数量。

对于每个测试用例,第一行包含一个整数 n (1≤n≤105)n~(1 \le n \le 10 ^ 5)n (1n105)。下一行包含一个长度为 nnn 的字符串。如果 c[i]c[i]c[i] 非零,则字符串的第 iii 个字符为 1,否则为 0

保证所有测试用例中 nnn 的总和不超过 10610^6106

输出格式

对于每个测试用例,输出庞教授调用该过程的最小可能次数。可以证明答案总是存在的。

输入输出样例 #1

输入 #1

3
5
10110
5
00000
5
11111

输出 #1

3
0
3

说明/提示

对于第一个例子,庞教授可以依次调用 update(1,1)update(2,-1)update(3,1)

对于第三个例子,庞教授可以依次调用 update(1,1)update(3,1)update(5,1)

题面翻译由 ChatGPT-4o 提供。

C++实现

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const int MAXN = 1e5 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int t, n;
int cnt[MAXN], ans;

int lowbit(int x) {
    return x & -x;
}

string s;

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> t;
    while (t--) {
        ans = 0;
        memset(cnt, 0, sizeof(cnt));
        cin >> n;
        cin >> s;
        for (int i = 1; i <= n; i++) {
            if (s[i - 1] == '0') {
                if (cnt[i] == 1)
                    ans++, cnt[i]++;
            } else {
                if (cnt[i] == 0)
                    ans++, cnt[i]++;
                int next = i + lowbit(i);
                if (next <= n)
                    cnt[next]++;
            }
        }
        cout << ans << endl;
    }
    return 0;
}

在这里插入图片描述

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值