题目来源:BZOJ 3343
思路:
分块
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 1000010;
int n, m, v[maxn], w[maxn], SZ, l[maxn], r[maxn], bl[maxn];
int a, b, c, cnt, lazy[maxn];
char ch[5];
int calc(int ll, int rr, int val){
int l = ll, r = rr, ans = rr+1;
while(l <= r){
int mid = (l+r)>>1;
if(w[mid] < val) l = mid + 1;
else ans = mid, r = mid - 1;
}
return rr - ans + 1;
}
int main(){
scanf("%d%d", &n, &m), SZ = sqrt(n);
for(int i = 1; i <= n; i ++) scanf("%d", &v[i]), w[i] = v[i];
for(int i = 1; i <= n; i ++) bl[i] =(i-1)/SZ + 1;
l[++cnt] = 1;
for(int i = 2; i <= n+1; i ++){
if(bl[i] != bl[i-1]) r[cnt] = i-1, l[++ cnt] = i;
}
cnt --;
for(int i = 1; i <= cnt; i ++) sort(w+l[i], w+r[i]+1);
for(int i = 1; i <= m; i ++) {
scanf("%s%d%d%d", ch+1, &a, &b, &c);
if(ch[1] == 'A'){
int ans = 0;
for(int i = bl[a]; i <= bl[b]; i ++){
if(i == bl[a] && a != l[i]){
for(int j = a; j <= r[i]; j ++){
if(v[j]+lazy[i] >= c) ans ++;
}
}else if(i == bl[b] && b != r[i]){
for(int j = l[i]; j <= b; j ++){
if(v[j]+lazy[i] >= c) ans ++;
}
}else{
ans += calc(l[i], r[i], c-lazy[i]);
}
}
printf("%d\n", ans);
}else{
for(int i = bl[a]; i <= bl[b]; i ++){
if(i == bl[a] && a != l[i]){
for(int j = l[i]; j <= r[i]; j ++) v[j] += lazy[i];
lazy[i] = 0;
for(int j = a; j <= r[i]; j ++) v[j] += c;
for(int j = l[i]; j <= r[i]; j ++) w[j] = v[j];
sort(w+l[i], w+r[i]+1);
}else if(i == bl[b] && b != r[i]){
for(int j = l[i]; j <= r[i]; j ++) v[j] += lazy[i];
lazy[i] = 0;
for(int j = l[i]; j <= b; j ++) v[j] += c;
for(int j = l[i]; j <= r[i]; j ++) w[j] = v[j];
sort(w+l[i], w+r[i]+1);
}else{
lazy[i] += c;
}
}
}
}
return 0;
}