代码:
#include <bits/stdc++.h>
#define int long long
#define endl '\n';
using namespace std;
const int N = 1e6 + 5;
int n, m, bl = 1010;
int a[N], pos[N], st[5005], ed[5005];
struct Ask{
int op, l, r, x, ans;
}b[N];
int l, r, tag, maxi;
int fa[N], rt[N], size[N], v[N];
int find(int x){
if(fa[x] == x){
return x;
}
return fa[x] = find(fa[x]);
}
void unionn(int x, int y){
if(rt[y]){
fa[rt[x]] = rt[y];
}
else{
rt[y] = rt[x];
v[rt[y]] = y;
}
size[y] += size[x];
rt[x] = size[x] = 0;
}
void build(){
maxi = 0;
for(int i = l; i <= r; i++){
if(!rt[a[i]]){
rt[a[i]] = i;
fa[i] = i;
v[i] = a[i];
}
else{
fa[i] = rt[a[i]];
}
maxi = max(maxi, a[i]);
size[a[i]]++;
}
}
void update1(int x){
if(x * 2 < maxi - tag){
for(int i = 1 + tag; i <= x + tag; i++){
if(rt[i]){
unionn(i, i + x);
}
}
tag += x;
}
else{
for(int i = x + 1 + tag; i <= maxi; i++){
if(rt[i]){
unionn(i, i - x);
}
}
maxi = min(maxi, x + tag);
}
}
void update2(int L, int R, int x){
if(L > R){
return ;
}
else{
for(int i = l; i <= r; i++){
a[i] = v[find(i)];
rt[a[i]] = size[a[i]] = 0;
a[i] -= tag;
}
for(int i = l; i <= r; i++){
fa[i] = 0;
}
tag = 0;
for(int i = L; i <= R; i++){
a[i] -= (a[i] > x ? x : 0);
}
build();
}
}
int query1(int x){
return (x + tag > 500000 ? 0 : size[x + tag]);
}
int query2(int L, int R, int x){
if(L > R){
return 0;
}
int cnt = 0;
for(int i = L; i <= R; i++){
cnt += (v[find(i)] - tag == x);
}
return cnt;
}
void Solve(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i];
pos[i] = (i - 1) / bl + 1;
}
for(int i = 1; i <= m; i++){
cin >> b[i].op >> b[i].l >> b[i].r >> b[i].x;
}
int now_bl = pos[n];
for(int i = 1; i <= now_bl; i++){
st[i] = (i - 1) * bl + 1;
ed[i] = i * bl;
}
ed[now_bl] = n;
for(int i = 1; i <= now_bl; i++){
l = st[i], r = ed[i];
build();
for(int j = 1; j <= m; j++){
if(l > b[j].r || r < b[j].l){
continue;
}
if(b[j].op == 1){
if(b[j].l <= l && r <= b[j].r){
update1(b[j].x);
}
else{
update2(max(l, b[j].l), min(r, b[j].r), b[j].x);
}
}
else{
if(b[j].l <= l && r <= b[j].r){
b[j].ans += query1(b[j].x);
}
else{
b[j].ans += query2(max(l, b[j].l), min(r, b[j].r), b[j].x);
}
}
}
}
for(int i = 1; i <= m; i++){
if(b[i].op == 2){
cout << b[i].ans << '\n';
}
}
}
signed main(){
Solve();
return 0;
}