简直和 UVA-12003 Array Transformer 解题笔记 一模一样。
把这题写一遍单纯是为了巩固分块实现能力。
实际写起来还真的 WA 了一发,确实有很多易错的地方,绝知此事要躬行。
尤其是循环的对象问题。是循环原序列还是块序列?想清楚再写。
#include<bits/stdc++.h>
#define N 500100
#define Q 100100
using namespace std;
int n,x[N],q;
int op,a,b,c;
int id[N],len,num;
vector<int> block[N];
inline void change(int a, int b){
int aid = id[a];
x[a] = b;
block[aid].clear();
for(int i = (aid-1)*len+1; id[i] == aid; i++){
block[aid].push_back(x[i]);
}
sort(block[aid].begin(), block[aid].end());
return;
}
inline int query(int a, int b, int c){
int aid = id[a], bid = id[b];
int ans = 0;
if(aid == bid){
for(int i = a; i <= b; i++){ // 注意循环的范围是 [a,b] ,而不是 [aid, bid]
if(x[i] >= c){
ans++;
}
}
return ans;
}
for(int i = a; id[i] == aid; i++){ // 注意循环是从 a 开始,不是从 aid 开始
if(x[i] >= c) ans++;
}
for(int i = b; id[i] == bid; i--){ // 注意循环是从 b 开始,不是从 bid 开始
if(x[i] >= c) ans++;
}
for(int i = aid+1; i <= bid-1; i++){
ans += block[i].end() - lower_bound(block[i].begin(), block[i].end(), c); // 想清楚为什么是这样
}
return ans;
}
int main(){
cin >> n;
len = sqrt(n);
num = n / len;
for(int i = 1; i <= n; i++){
cin >> x[i];
id[i] = (i-1) / len + 1;
block[id[i]].push_back(x[i]);
}
for(int i = 1; i <= num; i++){
sort(block[i].begin(), block[i].end());
}
cin >> q;
while(q--){
cin >> op;
if(op == 0){
cin >> a >> b >> c;
cout << query(a, b, c) << endl;
}
else{
cin >> a >> b;
change(a, b);
}
}
return 0;
}