题解:P10308 「Cfz Round 2」Osmanthus
szh_AK_all · · 题解
分析
当 打表的方法。
那么当
所以,我们可以在每次询问时,求出
int zero = 0;//代表0的个数
while (a[zero + 1] == 0 && zero + 1 <= n)
zero++;
用这样的方法求明显是超时的,那么可以进行优化。
由于每次修改只修改了一个数,但每次都要重新计算一遍
显然,当每次修改的
一:
二:
Code
#include <bits/stdc++.h>
using namespace std;
int a[300005], b[300005];
int main() {
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; i++)
cin >> a[i];
int la = 0;
while (a[la + 1] == 0 && la + 1 <= n)
la++;
while (q--) {
int x, p;
cin >> x >> p;
int zero = la;
if (a[x] != 0 && p == 0) {
if (x == la + 1) {
zero = la + 1;
while (a[zero + 1] == 0 && zero + 1 <= n)
zero++;
}
} else if (a[x] == 0 && p != 0) {
if (x <= la)
zero = x - 1;
}
la = zero;
a[x] = p;
if (n <= zero)
cout << 1;
else {
int kk = n;
kk -= zero;
int ans = 0;
for (int j = 1;; j *= 2) {
if (j == 1)
ans++;
else
ans += j / 2;
if (kk <= ans) {
cout << j;
break;
}
}
}
cout << endl;
}
}
赛时记录。
上述方法归根结底还是暴力的方法,这种方法可以通过可能是因为数据过水。
不过也可以用树状数组维护前缀和,而前缀
附上代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[300005], b[300005];
int c[300005];
int n;
void add(int x, int y) {
for (; x <= n; x += x & (-x))
c[x] += y;
}
int ask(int x) {
int ans = 0;
for (; x; x -= x & (-x))
ans += c[x];
return ans;
}
signed main() {
int q;
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> a[i];
add(i, a[i]);
}
while (q--) {
int x, p;
cin >> x >> p;
add(x, p - a[x]);
a[x] = p;
int l = 1, r = n, zero = 0;
while (l <= r) {
int mid = (l + r) / 2;
if (ask(mid) == 0) {
l = mid + 1;
zero = mid;
} else
r = mid - 1;
}
if (n <= zero)
cout << 1;
else {
int kk = n;
kk -= zero;
int ans = 0;
for (int j = 1;; j *= 2) {
if (j == 1)
ans++;
else
ans += j / 2;
if (kk <= ans) {
cout << j;
break;
}
}
}
cout << endl;
}
}