constint N = 3e6 + 8; int st[N], ed[N], siz[N], bel[N]; voidinit_block(int n) { int sq = sqrt(n); for (int i = 1; i <= sq; ++i) { st[i] = n / sq * (i - 1) + 1; ed[i] = n / sq * i; } ed[sq] = n; for (int i = 1; i <= sq; ++i) for (int j = st[i]; j <= ed[i]; ++j) bel[j] = i; for (int i = 1; i <= sq; ++i) siz[i] = ed[i] - st[i] + 1; } int arr[N], mark[N]; vector<int> v[N]; // 这里用vector存排序后的数组 voidupdate(int b)// 更新排序后的数组 { for (int i = 0; i <= siz[b]; ++i) v[b][i] = arr[st[b] + i]; sort(v[b].begin(), v[b].end()); } voideachT(){ int n = read(), m = read(); int sq = sqrt(n); init_block(n); for (int i = 1; i <= n; ++i) arr[i] = read(); for (int i = 1; i <= sq; ++i) for (int j = st[i]; j <= ed[i]; ++j) v[i].push_back(arr[j]); for (int i = 1; i <= sq; ++i) sort(v[i].begin(), v[i].end()); while (m--) { char o; scanf(" %c", &o); int l = read(), r = read(), k = read(); if (o == 'M') { if (bel[l] == bel[r]) // 如果同属一块直接暴力 { for (int i = l; i <= r; ++i) arr[i] += k; update(bel[l]); continue; } for (int i = l; i <= ed[bel[l]]; ++i) // 对零散块暴力处理 arr[i] += k; for (int i = st[bel[r]]; i <= r; ++i) arr[i] += k; update(bel[l]); update(bel[r]); for (int i = bel[l] + 1; i < bel[r]; ++i) // 打上标记 mark[i] += k; } else { int tot = 0; if (bel[l] == bel[r]) { for (int i = l; i <= r; ++i) if (arr[i] + mark[bel[l]] >= k) tot++; printf("%d\n", tot); continue; } for (int i = l; i <= ed[bel[l]]; ++i) if (arr[i] + mark[bel[l]] >= k) tot++; for (int i = st[bel[r]]; i <= r; ++i) if (arr[i] + mark[bel[r]] >= k) tot++; // 二分查找k-mark[i]的位置,因为整块都加上了mark[i]其实就相当于k减去mark[i] for (int i = bel[l] + 1; i < bel[r]; ++i) tot += v[i].end() - lower_bound(v[i].begin(), v[i].end(), k - mark[i]); printf("%d\n", tot); } } }