传送门
最直观的想法是维护N个元素每个时间的状态.这个做法显然不切实际,但似乎在线去做又没有什么很好的办法,所以只能考虑离线.
离线做法:因为只有单点查询,所以我们可以按照每个修改和询问的位置排序.然后只维护每个时间点的状态.修改可以拆分成两个操作,在l位置上修改time-m的值,在r+1位置撤销这次修改.然后离线的一个一个处理询问就可以了.而询问可以转化成1-time-1有多少个数>=y-a[pos].这个可以用分块来处理.对每个块排序然后跨块的时候二分就可以了.
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=(int)b;++i)
#define afir(i,a,b) for(int i=(int)a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#define bug puts("-------")
#define mpr(a,b) make_pair(a,b)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
inline void read(int &a){
int x = 0,f=1;char ch = getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){
x=x*10+ch-'0';ch=getchar();}
a = x*f;
}
struct C{
int p,x,tim;
}c[N];
struct Q{
int p,x,tim,id;
}q[N];
int n,m,blo,num,L[N],R[N],pos[N],a[N],ans[N],siz[N];
LL t[N],v[N],tag[N];
void build(){
int n = m+1;
blo = sqrt(n);
num = n/blo;
fir(i,1,num){
L[i] = (i-1)*blo+1;
R[i] = i*blo;
}
if(n % blo){
num++;
L[num] = R[num-1]+1;
R[num] = n;
}
fir(i,1,num){
siz[i] = tag[i] = 0;
fir(j,L[i],R[i]){
pos[j] = i;
t[j] = v[j] = 0;
siz[i]++;
}
}
}
bool c1(Q a,Q b){
return a.p == b.p?a.tim<b.tim:a.p<b.p;
}
bool c2(C a,C b){
return a.p == b.p?a.tim<b.tim:a.p<b.p;
}
void clr(int i){
if(tag[i]){
fir(j,L[i],R[i]) t[j] += tag[i];
tag[i] = 0;
}
}
void change(int l,int r,int x){
int p = pos[l],q = pos[r];
if(p == q){
clr(q);
fir(i,l,r) t[i] += x;
fir(i,L[q],R[q]) v[i] = t[i];
sort(v+L[p],v+R[p]+1);
}
else{
fir(i,p+1,q-1) tag[i] += x;
clr(p);clr(q);
fir(i,l,R[p]) t[i] += x;
fir(i,L[q],r) t[i] += x;
fir(i,L[p],R[p]) v[i] = t[i];
fir(i,L[q],R[q]) v[i] = t[i];
sort(v+L[p],v+R[p]+1);sort(v+L[q],v+R[q]+1);
}
}
int query(int l,int r,LL x){
int p = pos[l],q = pos[r],res = 0;
if(p == q){
clr(p);
fir(i,l,r) if(t[i] >= x) res++;
fir(i,L[q],R[q]) v[i] = t[i];
sort(v+L[p],v+R[p]+1);
}
else{
clr(p);clr(q);
fir(i,l,R[p]) if(t[i] >= x) res++;
fir(i,L[q],r) if(t[i] >= x) res++;
fir(i,L[q],R[q]) v[i] = t[i];
fir(i,L[p],R[p]) v[i] = t[i];
sort(v+L[p],v+R[p]+1);sort(v+L[q],v+R[q]+1);
fir(i,p+1,q-1){
LL cur = x-tag[i];
int p = lower_bound(v+L[i],v+R[i]+1,cur)-v;
res += (siz[i] - p + L[i]);
}
}
return res;
}
int main(){
read(n);read(m);
int t1=0,t2=0;
fir(i,1,n) read(a[i]);
fir(i,1,m){
int op;
read(op);
if(op == 1){
int l,r,x;
read(l);read(r);read(x);
++t1;c[t1].p = l;c[t1].x = x;c[t1].tim = i+1;
++t1;c[t1].p = r+1;c[t1].x = -x;c[t1].tim = i+1;
}
else++t2,read(q[t2].p),read(q[t2].x),q[t2].tim=i+1,q[t2].id = t2;
}
sort(c+1,c+1+t1,c2);
sort(q+1,q+1+t2,c1);
build();
int j = 1;
fir(i,1,t2){
while(j <= t1 && (c[j].p < q[i].p || (c[j].p == q[i].p && c[j].tim < q[i].tim))) change(c[j].tim,m+1,c[j].x),j++;
ans[q[i].id] = query(1,q[i].tim-1,q[i].x-a[q[i].p]);
}
fir(i,1,t2)
printf("%d\n",ans[i]);
return 0;
}