分块大法
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
char s[5];
int a[maxn], b[maxn];
int L[maxn], R[maxn], belong[maxn], lazy[maxn];
int block, num;
inline int read()
{
int s = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9'){ (s *= 10) += ch-'0'; ch = getchar(); }
return s*f;
}
int query(int l,int r,int x)
{
int ans = 0;
int p = belong[l], q = belong[r];
if(p == q){
for(register int i = l; i <= r; i++){
if(a[i]+lazy[p] >= x) ans++;
}
}
else{
int tmp;
for(register int i = p+1; i <= q-1; i++){
tmp = lower_bound(b+L[i],b+R[i]+1,x-lazy[i])-b;
ans += R[i]-tmp+1;
}
for(register int i = l; i <= R[p]; i++){
if(a[i]+lazy[p] >= x) ans++;
}
for(register int i = L[q]; i <= r; i++){
if(a[i]+lazy[q] >= x) ans++;
}
}
return ans;
}
void update(int l,int r,int x)
{
int p = belong[l], q = belong[r];
if(p == q){
for(register int i = l; i <= r; i++) a[i] += x;
for(register int i = L[p]; i <= R[p]; i++) b[i] = a[i];
sort(b+L[p],b+R[p]+1);
}
else{
for(register int i = p+1; i <= q-1; i++) lazy[i] += x;
for(register int i = l; i <= R[p]; i++) a[i] += x;
for(register int i = L[p]; i <= R[p]; i++) b[i] = a[i];
sort(b+L[p],b+R[p]+1);
for(register int i = L[q]; i <= r; i++) a[i] += x;
for(register int i = L[q]; i <= R[q]; i++) b[i] = a[i];
sort(b+L[q],b+R[q]+1);
}
}
int main()
{
int n, m, l, r, x;
n = read(); m = read();
for(register int i = 1; i <= n; i++){
a[i] = read();
b[i] = a[i];
}
block = (int)sqrt(n*1.0);
num = n/block;
for(register int i = 1; i <= num; i++){
L[i] = (i-1)*block+1;
R[i] = i*block;
}
if(R[num] < n) num++, L[num] = R[num-1]+1, R[num] = n;
for(register int i = 1; i <= num; i++){
for(register int j = L[i]; j <= R[i]; j++){
belong[j] = i;
}
sort(b+L[i],b+R[i]+1);
}
for(register int i = 1; i <= m; i++){
scanf("%s",s);
l = read(); r = read(); x = read();
if(s[0] == 'A'){
printf("%d\n",query(l,r,x));
}
else{
update(l,r,x);
}
}
return 0;
}