P2801 教主的魔法
P2801 教主的魔法
大致题意
给一个长度为\(n\)的序列\(a_i\),有\(m\)次操作,操作分为两种\(:\)
-
将区间\([l,r]\)上的所有数加上\(c\)
-
查询区间\([l,r]\)中小于\(c\)的数的个数
分析
数列分块入门题
对于查询操作,若\(l,r\)在同一个块内,直接暴力查询
反之,若不在同一个块内,则答案由三部分组成:以\(l\)开头的不完整块,以\(r\)结尾的不完整块,中间一连串连续的完整快
由于要查询大于等于\(c\)的值,考虑开一个数组\(t\)存块中元素排序后的值
对于不完整块,直接暴力查询
对于完整块,在\(t\)数组中二分查找\(c\)的值即可
修改操作也同理
若\(l,r\)在同一个块内,直接暴力查询
若不在一个块内,对于不完整块直接暴力修改,并更新该块在\(t\)数组中的值
对于完整块,使用类似于\(lazttag\)的方式保存即可
复杂度
预处理时,需对每个块内元素进行一次排序,复杂度为\(O(nlogn)\)
查询时,每次至多暴力修改\(2\sqrt n\)个元素,对\(\sqrt n\)个块内二分或排序,复杂度为\(O(\sqrt n +\sqrt n log\sqrt n )\)
总复杂度为\(O(\sqrt n +\sqrt n log\sqrt n + nlogn)\)
code
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int X=0; bool flag=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
if(flag) return X;
return ~(X-1);
}
const int MAXN = 1000010;
int a[MAXN],belong[MAXN],t[MAXN],n,m,st[MAXN],ed[MAXN],tag[MAXN];
void sort(int x){
for(int i=st[x];i<=ed[x];i++) t[i] = a[i];
sort(t+st[x],t+ed[x]+1);
}
void add(int l,int r,int val){
int x = belong[l],y = belong[r];
if(x==y){
for(int i=l;i<=r;i++) a[i]+=val;
sort(x);
return;
}
for(int i=l;i<=ed[x];i++) a[i]+=val;
for(int i=st[y];i<=r;i++) a[i]+=val;
for(int i=x+1;i<y;i++) tag[i]+=val;
sort(x);
sort(y);
}
int query(int l,int r,int val){
int res = 0;
int x = belong[l],y = belong[r];
if(x==y){
for(int i=l;i<=r;i++) if(a[i]+tag[x]>=val) res++;
return res;
}
for(int i=l;i<=ed[x];i++) if(a[i]+tag[x]>=val) res++;
for(int i=st[y];i<=r;i++) if(a[i]+tag[y]>=val) res++;
for(int i=x+1;i<y;i++) res += ed[i]-(lower_bound(t+st[i],t+ed[i]+1,val-tag[i])-t)+1;
return res;
}
int main(){
n = read(),m = read();
for(int i=1;i<=n;i++) a[i]=read();
int size = sqrt(n);
for(int i=1;i<=size;i++){
st[i] = (i-1)*size+1,ed[i] = i*size;
}
ed[size] = n;
for(int i=1;i<=size;i++){
for(int j=st[i];j<=ed[i];j++){
belong[j] = i;
}
sort(a+st[i],a+ed[i]+1);
sort(i);
}
for(int i=1;i<=m;i++){
char op;
int a,b,c;
cin>>op;
a = read(),b=read(),c=read();
if(op=='A'){
cout<<query(a,b,c)<<endl;
}
else{
add(a,b,c);
}
}
}