P9883 [EC Final 2021] Fenwick Tree
题目描述
庞教授正在讲授关于 Fenwick 树(也称为二叉索引树)的课程。
在 Fenwick 树中,我们有一个长度为 nnn 的数组 c[1…n]c[1\ldots n]c[1…n],初始时全为零(对于任何 1≤i≤n1\le i\le n1≤i≤n,c[i]=0c[i]=0c[i]=0)。每次,庞教授可以对某个位置 pospospos(1≤pos≤n1\leq pos \leq n1≤pos≤n)和一个值 valvalval 调用以下过程:
def update(pos, val):
while (pos <= n):
c[pos] += val
pos += pos & (-pos)
注意,对于任何正整数 pos,pos & (-pos) 等于 pos 的最大 2 的幂。
在这个过程中,valvalval 可以是任意实数。在调用了若干次(零次或多次)后,庞教授忘记了数组 ccc 中的确切值。他只记得对于每个从 111 到 nnn 的 iii,c[i]c[i]c[i] 是否为零。庞教授想知道,在假设他的记忆是准确的情况下,他调用该过程的最小可能次数。
输入格式
第一行包含一个整数 T (1≤T≤105)T~(1 \le T \le 10^5)T (1≤T≤105),表示测试用例的数量。
对于每个测试用例,第一行包含一个整数 n (1≤n≤105)n~(1 \le n \le 10 ^ 5)n (1≤n≤105)。下一行包含一个长度为 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考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
556

被折叠的 条评论
为什么被折叠?



