bzoj3343教主的魔法

传送门

分块板板。记录一个块加标记,不成整块的暴力改,改完之后用b数组维护块有序。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int n,q,sz,block,l,r,v;
int a[maxn],b[maxn],belong[maxn],Add[1010];
char op[5];
inline int read(){
	int x=0;char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return x;
}
inline void print(int x){
	if(x>9) print(x/10);
	putchar(x%10+'0');
}
inline void reset(int x){
	int l=(x-1)*sz+1,r=min(x*sz,n);
	for(int i=l;i<=r;++i) b[i]=a[i];
	sort(b+l,b+r+1);
}
inline void update(int l,int r,int v){
	if(belong[r]==belong[l]){for(int i=l;i<=r;++i)a[i]+=v;reset(belong[l]);}
	else{
		for(int i=l;i<=belong[l]*sz;++i) a[i]+=v;
		for(int i=(belong[r]-1)*sz+1;i<=r;++i) a[i]+=v;
		for(int i=belong[l]+1;i<belong[r];i++) Add[i]+=v;
		reset(belong[l]),reset(belong[r]);
	}
}
inline int count(int x,int v){
	int l=(x-1)*sz+1,r=min(x*sz,n);v=v-Add[x];
	int pos=lower_bound(b+l,b+r+1,v)-b;
	return r-pos+1;
}
inline int query(int l,int r,int v,int ret=0){
	if(belong[r]==belong[l]) for(int i=l;i<=r;++i) ret+=((a[i]+Add[belong[i]])>=v);
	else{
		for(int i=belong[l]+1;i<belong[r];i++) ret+=count(i,v); 
		for(int i=l;i<=belong[l]*sz;++i) ret+=((a[i]+Add[belong[i]])>=v);
		for(int i=(belong[r]-1)*sz+1;i<=r;++i) ret+=((a[i]+Add[belong[i]])>=v);
	}return ret;
}
int main(){
	n=read(),q=read(),sz=sqrt(n),block=(n-1)/sz+1;
	for(int i=1;i<=n;++i) b[i]=a[i]=read(),belong[i]=(i-1)/sz+1;
	for(int i=1;i<=block;++i) reset(i);
	while(q--){
		scanf("%s",op),l=read(),r=read(),v=read();
		if(op[0]=='A') print(query(l,r,v)),putchar(10);
		if(op[0]=='M') update(l,r,v);
	}
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值