20201110Day2 分块

1 分块1

区间加法,单点查询。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=5e4+10;
#define int long long
int read(){
	int a=0,op=1;char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
	return a*op;
}
int tag[maxn],a[maxn],belong[maxn];
int n,B;
int query(int q){return a[q]+tag[belong[q]];}
void change(int l,int r,int c){
	int bl=belong[l]+1,br=belong[r]-1;
	if(belong[l]==belong[r]) for(int i=l;i<=r;i++) a[i]+=c;
	else{
		for(int i=bl;i<=br;i++) tag[i]+=c;
		for(int i=l;belong[i]!=bl;i++) a[i]+=c;
		for(int i=r;belong[i]!=br;i--) a[i]+=c;
	}
	return ;
}
#undef int
int main(){
#define int long long
	n=read();
	B=sqrt(n);
	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1;
	int t=n;
	while(t--){
		int w,b,c,d;
		w=read(),b=read(),c=read(),d=read();
		if(!w) change(b,c,d);
		else printf("%lld\n",query(c));
	}
	return 0;
}

2 分块2

区间加法,查询区间内小于\(c^2\)的值的个数。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=5e4+10;
#define int long long
int read(){
	int a=0,op=1;char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
	return a*op;
}
int tag[maxn],a[maxn],belong[maxn];
int n,B;
vector<int> v[505];
void update(int b){
	v[b].clear();
	for(int i=(b-1)*B+1;belong[i]==b;i++) v[b].push_back(a[i]);
	sort(v[b].begin(),v[b].end());
}
void change(int l,int r,int c){
	int bl=belong[l]+1,br=belong[r]-1;
	if(belong[l]==belong[r]){
		for(int i=l;i<=r;i++) a[i]+=c;
		update(belong[l]);
	} 
	else{
		for(int i=bl;i<=br;i++) tag[i]+=c;
		for(int i=l;belong[l]==belong[i];i++) a[i]+=c;
		update(belong[l]);
		for(int i=r;belong[i]==belong[r];i--) a[i]+=c;
		update(belong[r]);
	}
}
int query(int l,int r,int c){
	int res=0,bl=belong[l]+1,br=belong[r]-1;
	if(belong[l]==belong[r]){
		for(int i=l;i<=r;i++) res+=(a[i]<c-tag[belong[l]]);
		return res;
	}
	for(int i=bl;i<=br;i++) res+=lower_bound(v[i].begin(),v[i].end(),c-tag[i])-v[i].begin();
	for(int i=l;belong[i]==belong[l];i++) res+=(a[i]<c-tag[belong[l]]);
	for(int i=r;belong[i]==belong[r];i--) res+=(a[i]<c-tag[belong[r]]);
	return res;
}
#undef int
int main(){
#define int long long
	n=read();
	B=sqrt(n);
	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1,v[belong[i]].push_back(a[i]);
	int t=n;
	int mb=belong[n];
	for(int i=1;i<=mb;i++) sort(v[i].begin(),v[i].end());
	while(t--){
		int w,b,c,d;
		w=read(),b=read(),c=read(),d=read();
		if(!w) change(b,c,d);
		else d*=d,printf("%lld\n",query(b,c,d));
	}
	return 0;
}

3 分块3

区间加法,求区间某个点的前驱(在他之前小于该点的最大值,没有输出-1)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
const int maxn=5e5+10;
#define int long long
int read(){
	int a=0,op=1;char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
	return a*op;
}
int tag[maxn],a[maxn],belong[maxn];
int n,B;
vector<int>que[1005];
void init(){
	for(int i=1;i<=belong[n];i++) sort(que[i].begin(),que[i].end());
}
void update(int x){
	que[x].clear();
	for(int i=(x-1)*B+1;belong[i]==x;i++) que[x].push_back(a[i]);
	sort(que[x].begin(),que[x].end());
}
void modify(int l,int r,int c){
	int bl=belong[l]+1,br=belong[r]-1;
	if(belong[l]==belong[r]){
		for(int i=l;i<=r;i++) a[i]+=c;
		update(belong[l]);
		return ;
	}
	for(int i=l;belong[l]==belong[i];i++) a[i]+=c;
	for(int i=bl;i<=br;i++) tag[i]+=c;
	for(int i=r;belong[i]==belong[r];i--) a[i]+=c;
	update(belong[l]),update(belong[r]);
}
int find(int a,int c){
	vector<int>::iterator it=lower_bound(que[a].begin(),que[a].end(),c-tag[a]);
	if(it==que[a].begin()) return -1;
	else {--it;return *it+tag[a];}
}
int query(int l,int r,int c){
	int res=-1;
	int bl=belong[l]+1,br=belong[r]-1;
	if(belong[l]==belong[r]){
		for(int i=l;i<=r;i++) if(a[i]+tag[belong[l]]<c) res=max(res,a[i]+tag[belong[l]]);
		return res;
	}
	for(int i=bl;i<=br;i++) res=max(res,find(i,c));
	for(int i=l;belong[l]==belong[i];i++) if(a[i]+tag[belong[l]]<c) res=max(res,a[i]+tag[belong[l]]);
	for(int i=r;belong[r]==belong[i];i--) if(a[i]+tag[belong[r]]<c) res=max(res,a[i]+tag[belong[r]]);
	return res;
}
#undef int
int main(){
#define int long long
	n=read();
	B=sqrt(n);
	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1,que[belong[i]].push_back(a[i]);
	int t=n;
	init();
	while(t--){
		int w,b,c,d;
		w=read(),b=read(),c=read(),d=read();
		if(!w) modify(b,c,d);
		else printf("%lld\n",query(b,c,d));
	}
	return 0;
}

分块4

区间加法,区间求和。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=5e5+10;
int sum[maxn];
#define int long long
int read(){
	int a=0,op=1;char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
	return a*op;
}
int tag[maxn],a[maxn],belong[maxn];
int n,B;
void add(int l,int r,int c){
	int bl=belong[l]+1,br=belong[r]-1;
	for(int i=l;i<=min(belong[l]*B,r);i++) a[i]+=c,sum[belong[i]]+=c;
	if(belong[l]!=belong[r]){
		for(int i=r;i>=(belong[r]-1)*B+1;i--) a[i]+=c,sum[belong[i]]+=c;
	}
	for(int i=bl;i<=br;i++) tag[i]+=c;
}
int query(int l,int r){
	int ans=0;
	int bl=belong[l]+1,br=belong[r]-1;
	for(int i=l;i<=min(belong[l]*B,r);i++) ans+=a[i]+tag[belong[i]];
	if(belong[l]!=belong[r]){
		for(int i=r;i>=(belong[r]-1)*B+1;i--) ans+=a[i]+tag[belong[i]];
	}
	for(int i=bl;i<=br;i++) ans+=sum[i]+B*tag[i];
	return ans;
}
#undef int
int main(){
#define int long long
	n=read();
	B=sqrt(n);
	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1,sum[belong[i]]+=a[i];
	int t=n;
	while(t--){
		int w,b,c,d;
		w=read(),b=read(),c=read(),d=read();
		if(!w) add(b,c,d);
		else printf("%lld\n",query(b,c)%(d+1));
	}
	return 0;
}

5 分块5

区间求和,区间元素开根号(下取整)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=5e5+10;
int sum[maxn];
#define int long long
int read(){
	int a=0,op=1;char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
	return a*op;
}
int tag[maxn],a[maxn],belong[maxn];
int n,B;
int flag[maxn];
void solve_sqrt(int x){
	if(flag[x]) return ;
	flag[x]=1;
	sum[x]=0;
	for(int i=(x-1)*B+1;i<=B*x;i++){
		a[i]=sqrt(a[i]),sum[x]+=a[i];
		if(a[i]>1) flag[x]=0;
	}
}
void add(int l,int r,int c){
	int bl=belong[l]+1,br=belong[r]-1;
	for(int i=l;i<=min(belong[l]*B,r);i++) sum[belong[l]]-=a[i],a[i]=sqrt(a[i]),sum[belong[l]]+=a[i];
	if(belong[l]!=belong[r]){
		for(int i=r;i>=(belong[r]-1)*B+1;i--) sum[belong[r]]-=a[i],a[i]=sqrt(a[i]),sum[belong[i]]+=a[i];
	}
	for(int i=bl;i<=br;i++) solve_sqrt(i);
}
int query(int l,int r){
	int ans=0;
	int bl=belong[l]+1,br=belong[r]-1;
	for(int i=l;i<=min(belong[l]*B,r);i++) ans+=a[i];
	if(belong[l]!=belong[r]){
		for(int i=r;i>=(belong[r]-1)*B+1;i--) ans+=a[i];
	}
	for(int i=bl;i<=br;i++) ans+=sum[i];
	return ans;
}
#undef int
int main(){
#define int long long
	n=read();
	B=sqrt(n);
	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1,sum[belong[i]]+=a[i];
	int t=n;
	while(t--){
		int w,b,c,d;
		w=read(),b=read(),c=read(),d=read();
		if(!w) add(b,c,d);
		else printf("%lld\n",query(b,c));
	}
	return 0;
}

6 分块6

单点插入,单点查询。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=5e5+10;
int sum[maxn];
#define int long long
int read(){
	int a=0,op=1;char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
	return a*op;
}
int tag[maxn],a[maxn],belong[maxn];
int n,m,B;
int flag[maxn];
int st[maxn],top;
vector<int> ve[maxn];
pair<int,int> query(int b){
	int x=1;
	while(b>ve[x].size()) b-=ve[x].size(),x++;
	return make_pair(x,b-1);
}
void rebuild(){
	top=0;
	for(int i=1;i<=m;i++){
		for(vector<int>::iterator j=ve[i].begin();j!=ve[i].end();j++)
			st[++top]=*j;
		ve[i].clear();
	}
	int blo2=sqrt(top);
	for(int i=1;i<=top;i++) ve[(i-1)/blo2+1].push_back(st[i]);
	m=(top-1)/blo2+1;
}
void insertt(int a,int b){
	pair<int,int> t=query(a);
	ve[t.first].insert(ve[t.first].begin()+t.second,b);
	if(ve[t.first].size()>20*B) rebuild();
}
#undef int
int main(){
#define int long long
	n=read();
	B=sqrt(n);
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=1;i<=n;i++) ve[(i-1)/B+1].push_back(a[i]);
	m=(n-1)/B+1;
	int t=n;
	while(t--){
		int w,b,c,d;
		w=read(),b=read(),c=read(),d=read();
		if(!w) insertt(b,c);
		else{
			pair<int,int> t=query(c);printf("%lld\n",ve[t.first][t.second]);
		}
	}
	return 0;
}

7 分块7

区间加法,区间乘法,单点查询。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=5e5+10;
const int mod=1e4+7;
int sum[maxn];
#define int long long
int read(){
	int a=0,op=1;char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
	return a*op;
}
int addtag[maxn],multag[maxn],a[maxn],belong[maxn];
int n,m,B;
void reset(int x){
	for(int i=(x-1)*B+1;i<=min(n,x*B);i++) a[i]=(a[i]*multag[x]+addtag[x])%mod;
	addtag[x]=0,multag[x]=1;
}	
int query(int q){return (a[q]*multag[belong[q]]+addtag[belong[q]])%mod;}
void add_change(int l,int r, int c){
	reset(belong[l]);
	int bl=belong[l]+1,br=belong[r]-1;
	for(int i=l;i<=min(belong[l]*B,r);i++) a[i]+=c,a[i]%=mod;
	if(belong[l]!=belong[r]){
		reset(belong[r]);
		for(int i=r;i>=(belong[r]-1)*B+1;i--) a[i]+=c,a[i]%=mod;
	}
	for(int i=bl;i<=br;i++) addtag[i]+=c,addtag[i]%=mod;
}
void mul_change(int l,int r,int c){
	reset(belong[l]);
	int bl=belong[l]+1,br=belong[r]-1;
	for(int i=l;i<=min(belong[l]*B,r);i++) a[i]*=c,a[i]%=mod;
	if(belong[l]!=belong[r]){
		reset(belong[r]);
		for(int i=r;i>=(belong[r]-1)*B+1;i--) a[i]*=c,a[i]%=mod;
	}
	for(int i=bl;i<=br;i++) addtag[i]*=c,addtag[i]%=mod,multag[i]*=c,multag[i]%=mod;
}
#undef int
int main(){
#define int long long
	n=read();
	B=sqrt(n);
	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1;
	for(int i=1;i<=belong[n];i++) multag[i]=1;
	int t=n;
	while(t--){
		int w,b,c,d;
		w=read(),b=read(),c=read(),d=read();
		if(w==0) add_change(b,c,d);
		else if(w==1) mul_change(b,c,d);
		else printf("%lld\n",query(c)%mod);
	}
	return 0;
}

8 分块8

区间查询等于c的元素个数,并将区间内的元素改为c

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=5e5+10;
const int mod=1e4+7;
int sum[maxn];
#define int long long
int read(){
	int a=0,op=1;char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') op=-1;c=getchar();}
	while(c>='0'&&c<='9') a*=10,a+=c^48,c=getchar();
	return a*op;
}
int tag[maxn],a[maxn],belong[maxn];
int n,m,B;
void reset(int x){
	if(tag[x]==-1) return ;
	for(int i=(x-1)*B+1;i<=x*B;i++) a[i]=tag[x];
	tag[x]=-1;
}
int solve(int l,int r,int c){
	int ans=0,bl=belong[l]+1,br=belong[r]-1;
	reset(belong[l]);
	for(int i=l;i<=min(r,B*belong[l]);i++){
		if(a[i]!=c) a[i]=c;
		else ans++;
	}
	if(belong[l]!=belong[r]){
		reset(belong[r]);
		for(int i=r;i>=(belong[r]-1)*B+1;i--){
			if(a[i]!=c) a[i]=c;
			else ans++;
		}
	}
	for(int i=bl;i<=br;i++){
		if(tag[i]!=-1){
			if(tag[i]!=c) tag[i]=c;
			else ans+=B;
		}
		else{
			for(int j=(i-1)*B+1;j<=i*B;j++){
				if(a[j]!=c) a[j]=c;
				else ans++;
			}
			tag[i]=c;
		}
	}
	return ans;
}
#undef int
int main(){
#define int long long
	memset(tag,-1,sizeof(tag));
	n=read();
	B=sqrt(n);
	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1;
	int t=n;
	while(t--){
		int w,b,c,d;
		b=read(),c=read(),d=read();
		printf("%lld\n",solve(b,c,d));
	}
	return 0;
}
posted @ 2020-11-10 14:42  刘子闻  阅读(67)  评论(0)    收藏  举报