loj数论分块

1

板子。

#include<bits/stdc++.h>
using namespace std;
#define in read()
int in{
	int cnt=0,f=1;char ch=0;
	while(!isdigit(ch)){
		ch=getchar();if(ch=='-')f=-1;
	}
	while(isdigit(ch)){
		cnt=cnt*10+ch-48;
		ch=getchar(); 
	}return cnt*f;
}
const int N=50003;
int n;
int block;
int a[N];
int belong[N],L[253],R[253],size,tag[253];
void modify(int l,int r,int key){
	if(belong[r]-belong[l]<=1){
		for(int i=l;i<=r;i++){
			//cout<<"modify "<<i<<" "<<key<<endl;
			a[i]+=key;
		}return;
	}
	for(int i=l;i<=R[belong[l]];i++){
		a[i]+=key;
	}
	for(int i=L[belong[r]];i<=r;i++)a[i]+=key;
	for(int i=belong[l]+1;i<=belong[r]-1;i++){
		tag[i]+=key;
	}
}
signed main(){
	n=in;
	block=sqrt(n);
	for(int l=1,r;l<=n;l=r+1){
		++size;
		r=l+block-1;L[size]=l;R[size]=r;
	}R[size]=n;
	for(int i=1;i<=size;i++){
		for(int j=L[i];j<=R[i];++j){
			//cout<<j<<" "<<i<<endl;
			belong[j]=i;
		}
	}
	//for(int i=1;i<=size;i++)cout<<L[i]<<" "<<R[i]<<endl;
	//for(int i=1;i<=n;i++)cout<<belong[i]<<" ";cout<<endl;
	for(int i=1;i<=n;i++)a[i]=in;
	int q=n;int op,l,r,c;
	while(q--){
		op=in;l=in;r=in;c=in;
		if(op==0){
			modify(l,r,c);
		}
		if(op==1){
			cout<<a[r]+tag[belong[r]]<<'\n';
			//cout<<a[r]<<" "<<tag[belong[r]]<<endl;
		}
	}
}

2

二分查就行。维护另一个数组来保持块内升序。

#include<bits/stdc++.h>
using namespace std;
#define in read()
#define int long long
int in{
	int cnt=0,f=1;char ch=0;
	while(!isdigit(ch)){
		ch=getchar();if(ch=='-')f=-1;
	}
	while(isdigit(ch)){
		cnt=cnt*10+ch-48;
		ch=getchar();
	}return cnt*f;
}
const int N=200003;
int n,a[N],d[N];
int size,block,L[503],R[503],belong[N],tag[503];
void modify(int l,int r,int key){
	if(belong[r]-belong[l]<=1){
		for(int i=l;i<=r;i++)a[i]+=key;
		for(int i=L[belong[l]];i<=R[belong[r]];i++){
			d[i]=a[i];
		}sort(d+L[belong[l]],d+R[belong[l]]+1);
		sort(d+L[belong[r]],d+R[belong[r]]+1);return;
	}
	for(int i=l;i<=R[belong[l]];i++){
		a[i]+=key;
	}
	for(int i=L[belong[r]];i<=r;i++){
		a[i]+=key;
	}
	for(int i=L[belong[l]];i<=R[belong[l]];i++)d[i]=a[i];
	for(int i=L[belong[r]];i<=R[belong[r]];i++)d[i]=a[i];
	sort(d+L[belong[l]],d+R[belong[l]]+1);
	sort(d+L[belong[r]],d+R[belong[r]]+1);
	for(int i=belong[l]+1;i<=belong[r]-1;i++){
		tag[i]+=key;
	}
	//sort(d+L[],a+R[l]+1);sort(a+L[r],a+R[r]+1);
}

int query(int l,int r,int key){
	//cout<<l<<" "<<r<<" "<<key<<endl;
//	cout<<"tag ";
//	for(int i=1;i<=2;i++)cout<<tag[i]<<" ";cout<<endl;
//	int sum=0;cout<<"a ";
//	for(int i=1;i<=4;i++)cout<<a[i]<<" ";cout<<endl;
	int sum=0;
	if(belong[r]-belong[l]<=1){
		for(int i=l;i<=r;i++)sum+=(tag[belong[i]]+a[i]<key)?1:0;return sum;
	}
	for(int i=l;i<=R[belong[l]];i++)sum+=(tag[belong[l]]+a[i]<key);
	for(int i=L[belong[r]];i<=r;i++)sum+=(tag[belong[r]]+a[i]<key);
	for(int i=belong[l]+1;i<=belong[r]-1;i++){
		sum+=(lower_bound(d+L[i],d+R[i]+1,key-tag[i]))-d-L[i];
	}
	return sum;
}
signed main(){
	n=in;
	for(int i=1;i<=n;i++)a[i]=in,d[i]=a[i];
	block=sqrt(n);
	for(int l=1,r;l<=n;l=r+1){
		r=l+block-1;++size;L[size]=l;R[size]=r;
	}R[size]=n;
	for(int i=1;i<=size;i++){
		for(int j=L[i];j<=R[i];j++)belong[j]=i;
	}
	for(int i=1;i<=size;i++)sort(d+L[i],d+R[i]+1);
	int q=n;
	while(q--){
		int op=in;int l=in;int r=in;int c=in;
		if(!op){
			modify(l,r,c);
		}
		else{
			cout<<query(l,r,c*c)<<'\n';
		} 
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值