BZOJ 3343: 教主的魔法【分块基础题

80 篇文章 0 订阅
2 篇文章 0 订阅

……应该是第一次好好写分块的题2333333好暴力23333

……总觉得写的好丑23333【以后分块就用yjq和laekov这两个变量名了,感觉稳得不行

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define MAXN 1000005
using namespace std;	int n,m;
inline int read(){
	register int ch = getchar();
	while(!isdigit(ch))	ch = getchar();
	register int rtn = 0 ;
	while(isdigit(ch))	rtn = rtn*10 + ch - '0' , ch = getchar() ;
	return rtn;
}

int laekov , num ;
int a[MAXN] , b[MAXN] , add[MAXN] , yjq[MAXN] ;

inline void reset(int id){
	int l = laekov * (id - 1) + 1 , r = min( laekov * id , n ) ;
	for(int i=l;i<=r;++i)	b[i] = a[i] ;
	sort(b+l,b+r+1);
}

inline void inqry(int L,int R,int C){
	int ans = 0 ;
	if(yjq[L]==yjq[R]){
		for(int i=L;i<=R;++i)	ans += (a[i]+add[yjq[L]] >= C) ;
		return void(printf("%d\n",ans)) ;
	}
	for(int i=L; yjq[i]==yjq[L]; ++i)	ans += (a[i]+add[yjq[i]] >= C) ;
	for(int i=R; yjq[i]==yjq[R]; --i)	ans += (a[i]+add[yjq[i]] >= C) ;
	for(int i=laekov*yjq[L]+1; yjq[i]<yjq[R]; i += laekov)
		ans += b+i+laekov 
			- lower_bound(b+i,b+i+laekov, C-add[yjq[i]]);
	printf("%d\n",ans);
}

inline void pushdown(int id){
	int L = laekov*(id-1) + 1,
	    R = min(laekov*id,n);
	for(int i=L;i<=R;++i)
		a[i] += add[id];
	reset(id);
}
inline void modify(int L,int R,int C){
	if(yjq[L]==yjq[R]){
		for(int i=L;i<=R;++i)
			a[i] += C;
		return void(pushdown(yjq[L]));
	}
	for(int i=L;yjq[i]==yjq[L];++i)
		a[i] += C;
	for(int i=R;yjq[i]==yjq[R];--i)
		a[i] += C;
	pushdown(yjq[L]) , pushdown(yjq[R]);
	for(int i=yjq[L]*laekov+1;
		yjq[i]<yjq[R];
		i += laekov)
		add[yjq[i]] += C;
}

char opt[5];
int read_l,read_r,read_c;
int main(){
	//freopen("magic.in","r",stdin);
	n = read() , m = read() ;
	laekov = sqrt(1.0*n);
	//printf("laekov = %d\n",laekov);

	for(int i=1;i<=n;++i)	a[i] = read() , yjq[i] = (i-1)/laekov + 1 ;
	num = n/laekov + (bool) (n%laekov) ;

	for(int i=1;i<=num;++i)	reset(i);

	while(m--){
		scanf("%s",opt);
		read_l = read() , read_r = read();
		read_c = read();
		opt[0]=='A'?
			inqry(read_l,read_r,read_c):
			modify(read_l,read_r,read_c);

		//for(int i=1;i<=n;++i)	printf("%d%c",b[i],i==n?'\n':' ');
	}

	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值