Connecting...

# 数列分块入门

#6277. 数列分块入门 1 - 题目 - LibreOJ

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10;
int n,a[N];
int bel[N],tot,block,l[N],r[N],tag[N];
void init(){
	block=sqrt(n)+1;
	tot=n/block;
	if(n%block)tot++;
	for(int i=1;i<=tot;++i){
		l[i]=(i-1)*block+1;
		r[i]=min(i*block,n);
	}
	for(int i=1;i<=n;++i)bel[i]=(i-1)/block+1;
	
}
void add(int x,int y,int c){
	if(y-x<=block){
		for(int i=x;i<=y;++i)a[i]+=c;
		return ;
	}
	for(int i=x;i<=r[bel[x]];++i)a[i]+=c;
	for(int i=l[bel[y]];i<=y;++i)a[i]+=c;
	for(int i=bel[x]+1;i<bel[y];++i)tag[i]+=c;
	
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	init();
	for(int i=1;i<=n;++i){
		int op,L,R,c;
		cin>>op>>L>>R>>c;
		if(op==0) add(L,R,c);
		if(op==1) cout<<tag[bel[R]]+a[R]<<"\n";
	}
	
	return 0;
} 

#6278. 数列分块入门 2 - 题目 - LibreOJ

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e4+10;
int n,a[maxn+10];
vector<int>v[5010];
int bel[maxn+10],block,tot,sum[maxn+10],l[maxn+10],r[maxn+10];
void init(){
	block=0.5*sqrt(n);
	tot=n/block;if(n%block)tot++;
	for(int i=1;i<=tot;++i){
		l[i]=(i-1)*block+1;
		r[i]=min(n,i*block);
	}
	for(int i=1;i<=n;++i) bel[i]=(i-1)/block+1 , v[bel[i]].push_back(a[i]);
	for(int i=1;i<=bel[n];++i)sort(v[i].begin(),v[i].end());
}
void reset(int x){
	v[x].clear();
	for(int i=l[x];i<=r[x];++i)v[x].push_back(a[i]);
	sort(v[x].begin(),v[x].end());
}
void add(int x,int y,int c){
	for(int i=x;i<=min(y,r[bel[x]]);++i)a[i]+=c;
	reset(bel[x]);
	if(bel[x]!=bel[y]){
		for(int i=l[bel[y]];i<=y;++i)a[i]+=c;
		reset(bel[y]);
	}
		
	for(int i=bel[x]+1;i<bel[y];++i)sum[i]+=c;
	
}
int q(int x,int y,int c){
	int cnt=0;
	for(int i=x;i<=min(y,r[bel[x]]);++i) cnt+=(sum[bel[x]]+a[i]<c);
	if(bel[x]!=bel[y]) for(int i=l[bel[y]];i<=y;++i) cnt+=(sum[bel[y]]+a[i]<c);
	for(int i=bel[x]+1;i<bel[y];++i){
		int tmp=c-sum[i];
		cnt+=lower_bound(v[i].begin(),v[i].end(),tmp)-v[i].begin();
	}
	return cnt;
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	init();
	for(int i=1;i<=n;++i){
		int op,l,r,c;
		cin>>op>>l>>r>>c;
		if(op==0)add(l,r,c);
		if(op==1)cout<<q(l,r,c*c)<<"\n";
	}
	
	return 0;
}

#6279. 数列分块入门 3 - 题目 - LibreOJ

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,a[N];
int bel[N],tot,block,l[1000],r[1000],tag[1000];
vector<int>v[1000];
void init(){
	block=sqrt(n)+1;
	tot=n/block;
	if(n%block)tot++;
	for(int i=1;i<=tot;++i){
		l[i]=(i-1)*block+1;
		r[i]=min(i*block,n);
	}
	for(int i=1;i<=n;++i)bel[i]=(i-1)/block+1;
	for(int i=1;i<=tot;++i){
		for(int j=l[i];j<=r[i];++j) v[i].push_back(a[j]);
		sort(v[i].begin(),v[i].end());
	}
}
void reset(int blo){
	v[blo].clear();
	for(int i=l[blo];i<=r[blo];++i) v[blo].push_back(a[i]);
	sort(v[blo].begin(),v[blo].end());
}
void add(int x,int y,int c){
	if(y-x<=block){
		for(int i=x;i<=y;++i)a[i]+=c;
		reset(bel[x]);if(bel[x]!=bel[y])reset(bel[y]);
		return ;
	}
	for(int i=x;i<=r[bel[x]];++i)a[i]+=c;
	for(int i=l[bel[y]];i<=y;++i)a[i]+=c;
	for(int i=bel[x]+1;i<bel[y];++i)tag[i]+=c;
	reset(bel[x]);
	if(bel[x]!=bel[y])reset(bel[y]);
}
int q(int x,int y,int c){
	if(y-x<=block){
		int ans=-INT_MAX;
		for(int i=x;i<=y;++i){
			if(a[i]+tag[bel[i]]>=c)continue;
			ans=max(ans,a[i]+tag[bel[i]]);
		}
		if(ans==-INT_MAX)return -1;
		return ans;
	}
	int ans=-INT_MAX;
	for(int i=x;i<=r[bel[x]];++i){
		if(a[i]+tag[bel[i]]>=c)continue;
		ans=max(ans,a[i]+tag[bel[i]]);
	}
	for(int i=l[bel[y]];i<=y;++i){
		if(a[i]+tag[bel[i]]>=c)continue;
		ans=max(ans,a[i]+tag[bel[i]]);
	}
	for(int i=bel[x]+1;i<bel[y];++i){
		int it=lower_bound(v[i].begin(),v[i].end(),c-tag[i])-v[i].begin();
		it--;
		if(it==-1)continue;
		ans=max(ans,v[i][it]+tag[i]);
	}
	if(ans==-INT_MAX)return -1;
	return ans;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	init();
	for(int i=1;i<=n;++i){
		int op,L,R,c;
		cin>>op>>L>>R>>c;
		if(op==0) add(L,R,c);
		if(op==1) cout<<q(L,R,c)<<"\n";
	}
	return 0;
} 

#6280. 数列分块入门 4 - 题目 - LibreOJ

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int N=5e4+10;
int n,a[N];
int bel[N],tot,block,l[1000],r[1000],tag[1000],sum[1000];
void reset(int x){
	sum[x]=0;
	for(int i=l[x];i<=r[x];++i) sum[x]+=a[i];
}
void init(){
	block=sqrt(n)+1;
	tot=n/block;
	if(n%block)tot++;
	for(int i=1;i<=tot;++i){
		l[i]=(i-1)*block+1;
		r[i]=min(i*block,n);
	}
	for(int i=1;i<=n;++i)bel[i]=(i-1)/block+1;
	for(int i=1;i<=tot;++i)reset(i);
}
void add(int x,int y,int c){
	if(y-x<=block){
		for(int i=x;i<=y;++i)a[i]+=c;
		reset(bel[x]);if(bel[x]!=bel[y])reset(bel[y]);
		return ;
	}
	for(int i=x;i<=r[bel[x]];++i)a[i]+=c;
	for(int i=l[bel[y]];i<=y;++i)a[i]+=c;
	for(int i=bel[x]+1;i<bel[y];++i)tag[i]+=c;
	reset(bel[x]);
	if(bel[x]!=bel[y])reset(bel[y]);
}

int q(int x,int y,int mod){
	int sm=0;
	if(y-x<=block){
		for(int i=x;i<=y;++i)sm+=a[i]+tag[bel[i]],sm%=mod;
		return sm%mod;
	}
	for(int i=x;i<=r[bel[x]];++i)sm+=a[i]+tag[bel[i]],sm%=mod;
	for(int i=l[bel[y]];i<=y;++i)sm+=a[i]+tag[bel[i]],sm%=mod;
	for(int i=bel[x]+1;i<bel[y];++i)sm+=block*tag[i]%mod+sum[i],sm%=mod;
	return (sm%mod+mod)%mod;
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	init();
	for(int i=1;i<=n;++i){
		int op,L,R,c;
		cin>>op>>L>>R>>c;
		if(op==0) add(L,R,c);
		if(op==1) cout<<q(L,R,c+1)<<"\n";
	}
	return 0;
} 

#6281. 数列分块入门 5 - 题目 - LibreOJ

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int N=5e4+10;
int n,a[N];
int bel[N],tot,block,l[N],r[N],tag[N],sum[1000],mx[1000];
int get(int tmp,int k){
	if(tmp==1)return 1;
	while(k--){
		tmp=(int)sqrt(tmp);
		if(tmp==1)return 1;
	}return tmp;
}
void reset(int x){
	sum[x]=0;
	mx[x]=-INT_MAX;
	for(int i=l[x];i<=r[x];++i){
		a[i]=get(a[i],tag[x]);
		sum[x]+=a[i];
		mx[x]=max(mx[x],a[i]);
	}
	tag[x]=0;
}
void init(){
	block=sqrt(n)+1;
	tot=n/block;
	if(n%block)tot++;
	for(int i=1;i<=tot;++i){
		l[i]=(i-1)*block+1;
		r[i]=min(i*block,n);
	}
	for(int i=1;i<=n;++i){
		bel[i]=(i-1)/block+1;
		mx[bel[i]]=max(mx[bel[i]],a[i]);
	}
	for(int i=1;i<=tot;++i) reset(i);
}
void sq(int x,int y){
	if(y-x<=block){
		for(int i=x;i<=y;++i)a[i]=(int)sqrt(a[i]);
		reset(bel[x]);if(bel[x]!=bel[y])reset(bel[y]);
		return ;
	}
	for(int i=x;i<=r[bel[x]];++i)a[i]=(int)sqrt(a[i]);
	for(int i=l[bel[y]];i<=y;++i)a[i]=(int)sqrt(a[i]);
	for(int i=bel[x]+1;i<bel[y];++i)tag[i]++;
	reset(bel[x]);if(bel[x]!=bel[y])reset(bel[y]);
}
int q(int x,int y){
	if(y-x<=block){
		int sm=0;
		for(int i=x;i<=y;++i) sm+=get(a[i],tag[bel[i]]);
		return sm;
	}
	int sm=0;
	reset(bel[x]);if(bel[x]!=bel[y])reset(bel[y]);
	for(int i=x;i<=r[bel[x]];++i)sm+=a[i];
	for(int i=l[bel[y]];i<=y;++i)sm+=a[i];
	for(int i=bel[x]+1;i<bel[y];++i){
		if(tag[i]==0||mx[i]==1){
			sm+=sum[i]; continue;
		}
		reset(i);
		sm+=sum[i];
	}
	return sm;
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	init();
	for(int i=1;i<=n;++i){
		int op,L,R,c;
		cin>>op>>L>>R>>c;
		if(op==0) sq(L,R);
		if(op==1) cout<<q(L,R)<<"\n";
	}
	
	return 0;
} 

#6282. 数列分块入门 6 - 题目 - LibreOJ

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,a[N];
int block,tot,bel[N],L[N],R[N],cnt=0;
vector<int>v[N],p;
void reset(){
	p.clear();
	for(int i=1;i<=tot;++i){
		for(auto j:v[i]) p.push_back(j);
		v[i].clear();
	}
	block=sqrt(p.size())+1;tot=p.size()/block;
	if(p.size()%block)tot++;
	for(int i=1;i<=n;++i){
		bel[i]=(i-1)/block+1;
		v[bel[i]].push_back(p[i-1]);
	}
}
void init(){
	cin>>n;cnt=n;
	for(int i=1;i<=n;++i)cin>>a[i];
	block=sqrt(n);tot=n/block;
	if(n%block)tot++;
	for(int i=1;i<=n;++i){
		bel[i]=(i-1)/block+1;
		v[bel[i]].push_back(a[i]);
	}
}
void ins(int l,int r){
	for(int i=1;i<=tot;++i){
		if(v[i].size()<l){
			l-=v[i].size();
			continue;
		}
		v[i].insert(v[i].begin()+l-1,r);
		break;
	}
}
void find(int x){
	for(int i=1;i<=tot;++i){
		if(v[i].size()<x){
			x-=v[i].size();
			continue;
		}
		cout<<v[i][x-1]<<"\n";
		break;
	}
}
void debug(){
	puts("\n");
	for(int i=1;i<=tot;++i){
		for(auto j:v[i])cout<<j<<" ";
	}puts("\n");
}
bool check(){
	for(int i=1;i<=tot;++i){
		if(v[i].size()>4*sqrt(cnt))return 1;
	}return 0;
}
int main(){
//	ios::sync_with_stdio(0),cin.tie(0);
	init();
	for(int i=1;i<=n;++i){
		int op,l,r,c;
		cin>>op>>l>>r>>c;
		if(op==0){
			ins(l,r);
			cnt++;
		}
		if(op==1){
			find(r);
		}
		if(check())reset();
//		debug();
	}
	return 0;
}

#6283. 数列分块入门 7 - 题目 - LibreOJ

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int __int128
const int N=1e5+10,mod=10007;
ll n,a[N],bel[N],l[N],r[N],block,tot;
int t1[N],t2[N];
void reset(int x){
	for(int i=l[x];i<=r[x];++i) a[i]=a[i]*t2[x]+t1[x],a[i]%=mod;
	t2[x]=1; t1[x]=0;
}
void init()
{
	cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	block=int(0.5*sqrt(n))+1;tot=n/block;
	if(n%block)tot++;
	for(ll i=1;i<=tot;++i){
		l[i]=(i-1)*block+1;
		r[i]=min(n,i*block);
		t2[i]=1;
	}
	for(ll i=1;i<=n;++i){
		bel[i]=(i-1)/block+1;
	}
}
void add(int x,int y,int c){
	reset(bel[x]);
	if(bel[x]!=bel[y])reset(bel[y]);
	if(y-x<=block){
		for(int i=x;i<=y;++i){
			a[i]+=c;
		}
		return ;
	}
	for(int i=x;i<=r[bel[x]];++i){
		a[i]+=c;
	}
	for(int i=l[bel[y]];i<=y;++i){
		a[i]+=c;
	}
	for(int i=bel[x]+1;i<bel[y];++i){
		t1[i]+=c;
	}
}
void mul(int x,int y,int c){
	reset(bel[x]);
	if(bel[x]!=bel[y])reset(bel[y]);
	if(y-x<=block){
		for(int i=x;i<=y;++i){
			a[i]*=c;
			a[i]%=mod;
		}
		return ;
	}
	for(int i=x;i<=r[bel[x]];++i){
		a[i]*=c;
		a[i]%=mod;
	}
	for(int i=l[bel[y]];i<=y;++i){
		a[i]*=c;
		a[i]%=mod;
	}
	for(int i=bel[x]+1;i<bel[y];++i){
		t1[i]*=c;
		t2[i]*=c;
		t2[i]%=mod;
		t1[i]%=mod;
	}
}
void q(int x){
	cout<<(ll)((a[x]*t2[bel[x]]%mod+t1[bel[x]]%mod)%mod)<<"\n";
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0);
	init();
	for(int i=1;i<=n;++i){
		ll op,L,R,c;
		cin>>op>>L>>R>>c;
		if(op==0){
			add(L,R,c);
		}
		if(op==1){
			mul(L,R,c);
		}
		if(op==2){
			q(R);
		}
	}
	return 0;
}
/*
ans[i]= a[i]*t2[i]+t1[i]
*/

#6284. 数列分块入门 8 - 题目 - LibreOJ

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10,inf=-LLONG_MAX;
int n,a[N];
int block,tot,l[N],r[N],bel[N],tag[N];
void init(){
	cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	block=sqrt(n)+1;
	tot=n/block;
	if(n%block)tot++;
	for(int i=1;i<=tot;++i){
		l[i]=(i-1)*block+1;
		r[i]=min(i*block,n);
		tag[i]=inf;
	}
	for(int i=1;i<=n;++i) 	bel[i]=(i-1)/block+1;
}
void reset(int x){
	if(tag[x]==inf)return ;
	for(int i=l[x];i<=r[x];++i){
		a[i]=tag[x];
	}
	tag[x]=inf;
}
int q(int x,int y,int c){
	reset(bel[x]);
	if(bel[x]!=bel[y])reset(bel[y]);
	if(y-x<=block){
		int cnt=0;
		for(int i=x;i<=y;++i){
			if(a[i]==c)cnt++;
			a[i]=c;
		}
		return cnt;
	}
	int cnt=0;
	for(int i=x;i<=r[bel[x]];++i){
		if(a[i]==c)cnt++;
		a[i]=c;
	}
	for(int i=l[bel[y]];i<=y;++i){
		if(a[i]==c)cnt++;
		a[i]=c;
	}
	for(int i=bel[x]+1;i<bel[y];++i){
		if(tag[i]==c)cnt+=block;
		else if(tag[i]==inf){
			for(int j=l[i];j<=r[i];++j)cnt+=(a[j]==c);
		}
		tag[i]=c;
	}
	return cnt;
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0);
	init();
	for(int i=1;i<=n;++i){
		int op,L,R,c;
		cin>>L>>R>>c;
		cout<<q(L,R,c)<<"\n";
	}
	return 0;
}

#6285. 数列分块入门 9 - 题目 - LibreOJ

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10,M=5e4+10;
int n,m,X,A[N]/*原a_i*/,tmp[N],a[N]/*离散化后编号*/,t[N]/*编号对应的值*/,len;
int cnt[1403][N]/*某个数出现次数对块前缀和*/,tcnt[N],block,tot,bel[N],mr[1402][1402]/*块内众数*/,l[1402],r[1402];
void init(){
	cin>>n;
	for(int i=1;i<=n;++i)cin>>A[i],tmp[i]=A[i];
	sort(tmp+1,tmp+1+n);
	len=unique(tmp+1,tmp+1+n)-(tmp+1);//不同元素个数 
	for(int i=1;i<=n;++i) a[i]=lower_bound(tmp+1,tmp+len+1,A[i])-tmp,t[a[i]]=A[i];
	block=(int)(sqrt(n))+1;
	tot=n/block;if(n%block)tot++;
	for(int i=1;i<=n;++i){
		bel[i]=(i-1)/block+1;
	}
	for(int i=1;i<=tot;++i){
		l[i]=(i-1)*block+1;
		r[i]=min(i*block,n);
		for(int j=l[i];j<=r[i];++j) cnt[i][a[j]]++;
	}
	for(int j=1;j<=tot;++j)
		for(int i=1;i<=len;++i)
			cnt[j][i]+=cnt[j-1][i];
	for(int i=1;i<=tot;++i){
		for(int j=1;j<=len;++j)tcnt[j]=0;
		for(int j=i;j<=tot;++j){
			mr[i][j]=mr[i][j-1];
			for(int k=l[j];k<=r[j];++k) {
				tcnt[a[k]]++;
				if(tcnt[mr[i][j]]<tcnt[a[k]])mr[i][j]=a[k];
				else if(tcnt[mr[i][j]]==tcnt[a[k]]){if(mr[i][j]>a[k])mr[i][j]=a[k];}
			}
		}
	}
}
void q(int x,int y){
	if(y-x<=block){
		for(int i=x;i<=y;++i) tcnt[a[i]]=0;
		for(int i=x;i<=y;++i) tcnt[a[i]]++;
		int ans=a[x];
		for(int i=x;i<=y;++i){
			if(tcnt[ans]<tcnt[a[i]])ans=a[i];
			
			else if(tcnt[ans]==tcnt[a[i]]) {if(ans>a[i])ans=a[i];}
		}
		cout<<(X=t[ans])<<"\n";
		return ;
	}
	for(int i=x;i<=r[bel[x]];++i) tcnt[a[i]]=cnt[bel[y]-1][a[i]]-cnt[bel[x]][a[i]];
	for(int i=l[bel[y]];i<=y;++i) tcnt[a[i]]=cnt[bel[y]-1][a[i]]-cnt[bel[x]][a[i]];
	tcnt[mr[bel[x]+1][bel[y]-1]]= cnt[bel[y]-1][mr[bel[x]+1][bel[y]-1]] -cnt[bel[x]][mr[bel[x]+1][bel[y]-1]];
	for(int i=x;i<=r[bel[x]];++i) tcnt[a[i]]++;
	for(int i=l[bel[y]];i<=y;++i) tcnt[a[i]]++;
	int ans=a[x];
	for(int i=x;i<=r[bel[x]];++i){
		if(tcnt[ans]<tcnt[a[i]])ans=a[i];
		else if(tcnt[ans]==tcnt[a[i]]) {if(ans>a[i])ans=a[i];}
	}
	for(int i=l[bel[y]];i<=y;++i){
		if(tcnt[ans]<tcnt[a[i]])ans=a[i];
		else if(tcnt[ans]==tcnt[a[i]]) {if(ans>a[i])ans=a[i];}
	}
	
	if(bel[x]+1<=bel[y]-1){
		if(tcnt[ans]<tcnt[mr[bel[x]+1][bel[y]-1]])ans=mr[bel[x]+1][bel[y]-1];
		else if(tcnt[ans]==tcnt[mr[bel[x]+1][bel[y]-1]]) {if(ans>mr[bel[x]+1][bel[y]-1])ans=mr[bel[x]+1][bel[y]-1];}
	}
	cout<<(X=t[ans])<<"\n";return; 
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0);
	init();
	for(int i=1;i<=n;++i)
	{	
		int L,R;
		cin>>L>>R;
		q(L,R);
	}
	return 0;
}
posted @ 2025-04-13 16:30  余亦宸  阅读(19)  评论(0)    收藏  举报