题目链接
题目解法
这道题需要打破一个常规的思路:维护每个时间的序列
而这题需要反着做:维护下标的每个时间的序列
我们令
t
t
t 为修改或查询操作的时间
我们发现对于修改操作,只需要在位置
l
l
l 处把
[
t
,
q
]
+
x
[t,q] +x
[t,q]+x,在位置
r
+
1
r+1
r+1 处
[
t
,
q
]
−
x
[t,q] -x
[t,q]−x 就可以了
对于询问操作,我们发现需要求
[
0
,
t
−
1
]
[0,t-1]
[0,t−1] 中比
y
−
a
[
p
]
y-a[p]
y−a[p] 大的数的个数
做过
l
o
j
loj
loj 分块
2
2
2 的可以想到用分块对每个块内进行排序
这样对于每次修改和询问时间复杂度都是
O
(
l
o
g
n
n
)
O(logn\sqrt n)
O(lognn)
所以总体时间复杂度 O ( q l o g n n ) O(qlogn\sqrt n) O(qlognn)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N(100100),Q(100100);
struct Node{
int id,p,y;
}query[Q],modify[Q<<1];
int n,q,ans[Q];
int B,pos[Q],_l[Q],_r[Q];
int a[N],b[Q],tag1[Q],tag2[Q];
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
void _sort(int k){
for(int i=_l[k];i<=_r[k];i++) b[i]=tag1[i];
sort(b+_l[k],b+_r[k]+1);
}
void update(int l,int r,int k){
if(pos[l]==pos[r]){
for(int i=l;i<=r;i++) tag1[i]+=k;
_sort(pos[l]);
}
else{
int i=l,j=r;
while(pos[i]==pos[l]) tag1[i++]+=k;
while(pos[j]==pos[r]) tag1[j--]+=k;
_sort(pos[l]),_sort(pos[r]);
for(int d=pos[i];d<=pos[j];d++)
tag2[d]+=k;
}
}
int ask(int l,int r,int k){
int res=0;
if(pos[l]==pos[r]){
for(int i=l;i<=r;i++)
if(tag1[i]+tag2[pos[i]]>=k) res++;
}
else{
int i=l,j=r;
while(pos[i]==pos[l]){
if(tag1[i]+tag2[pos[i]]>=k) res++;
i++;
}
while(pos[j]==pos[r]){
if(tag1[j]+tag2[pos[j]]>=k) res++;
j--;
}
for(int d=pos[i];d<=pos[j];d++){
int pos=lower_bound(b+_l[d],b+_r[d]+1,k-tag2[d])-b;
res+=_r[d]-pos+1;
}
}
return res;
}
bool cmp(const Node &x,const Node &y){
return x.p!=y.p?x.p<y.p:x.id<y.id;
}
void init(){
B=sqrt(q);
for(int i=1;i<=q;i++)
pos[i]=(i-1)/B+1;
for(int i=1;i<=pos[q];i++)
_l[i]=_r[i-1]+1,_r[i]=i*B;
_r[pos[q]]=q;
}
signed main(){
n=read(),q=read();
for(int i=1;i<=n;i++)
a[i]=read();
init();
int mq=0,mt=0;
for(int i=1,op,x,y,z;i<=q;i++){
op=read(),x=read(),y=read();
if(op==1){
z=read();
modify[++mt]={i,x,z},modify[++mt]={i,y+1,-z};
}
else query[++mq]={i,x,y};
}
sort(query+1,query+mq+1,cmp);
sort(modify+1,modify+mt+1,cmp);
memset(ans,-1,sizeof(ans));
for(int i=1,j=1;i<=mq;i++){
while(j<=mt&&modify[j].p<=query[i].p){
update(modify[j].id,q,modify[j].y);
j++;
}
Node t=query[i];
ans[t.id]=ask(0,t.id-1,t.y-a[t.p]);
}
for(int i=1;i<=q;i++)
if(ans[i]!=-1)
printf("%lld\n",ans[i]);
return 0;
}