Loading

分块练习

分块练习

P4109 定价

思路

由于区间范围太大,考虑将区间分块

\(1e5\) 个数字分成一块,\(1\sim 10^5\) 结果为 \(5\)\(a\cdot10^5+1\sim(a+1)\cdot 10^5\) 结果为 \((a+1)\cdot 10^5\)

这样可以分成 \(10^4\) 个块,每次查询就是 \(O(10^5)\)

总时间复杂度为 \(O(T\cdot 10^5)\)

可以通过本题

code

#include<bits/stdc++.h>
using namespace std;

const int N=1e4+1;
const int M=1e5;

inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}

int l[N],r[N],v[N],val[N];

inline int work(int x){
	int tot=0;
	for(;x;++tot,x/=10);
	return tot;
}

inline int cal(int x){
	while(x%10==0&&x) x/=10;
	return x%10==5?work(x)*2-1:work(x)*2;
}

inline void pre(){
	for(int i=1;i<N;++i){
		l[i]=(i-1)*M;
		r[i]=i*M;
		v[i]=r[i];
		val[i]=cal(i);
	}
	v[1]=5;
	val[1]=1;
}

inline int solve(int x,int y){
	int res=1e9+1,ans;
	int lx=x/M+1,ly=y/M+1;
	if(lx==ly){
		for(int i=x;i<=y;++i){
			if(res>cal(i)){
				res=cal(i);
				ans=i;
			}
		}
		return ans;
	}
	for(int i=x;i<=r[lx];++i)
		if(res>cal(i)){
			res=cal(i);
			ans=i;
		}
	for(int i=lx+1;i<=ly-1;++i)
		if(res>val[i]){
			res=val[i];
			ans=v[i];
		}
	for(int i=l[ly];i<=y;++i)
		if(res>cal(i)){
			res=cal(i);
			ans=i;
		}
	return ans;
}

signed main(){
	pre();
	int T=read();
	while(T--){
		int x=read(),y=read();
		cout<<solve(x,y)<<endl;
	}
}

CF920F SUM and REPLACE

思路

易得 \(d(1)=1\)\(d(2)=2\),因此当一个区间内所有的数都 \(\le2\) 的时候修改操作就没有了意义

因为对于 \(\forall x\)\(d(x)\le2\cdot \sqrt x\)

所以暴力修改序列的话复杂度是 \(ok\)

\(so\) 这个题变成了暴力+区间求和

可以用分块

code

#include<bits/stdc++.h>
using namespace std;

#define int long long

const int N=3e5+5;
const int M=1e6+5;

inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}

int n,m,sz;
int a[N],d[M],bl[N];
int v[N],mx[N];
int L[N],R[N];

inline void get_d(){
	for(int i=1;i<(int)1e6+5;++i)
		for(int j=1;i*j<(int)1e6+5;++j)
			++d[i*j];
}

inline void C(int x){
	v[x]=mx[x]=0;
	for(int i=L[x];i<=R[x];++i){
		v[x]+=a[i];
		mx[x]=max(mx[x],a[i]);
	}
}

inline void D(int l,int r){
	for(int i=l;i<=r;++i)
		if(a[i]>2) a[i]=d[a[i]];
}

inline void build(){
	for(int i=1;i<=bl[n];++i)
		C(i);
}

inline void update(int x,int y){
	int l=bl[x],r=bl[y];
	if(l==r){
		D(x,y);
		C(l);
		return;
	}
	D(x,R[l]);
	C(l);
	D(L[r],y);
	C(r);
	for(int i=l+1;i<=r-1;++i)
		if(mx[i]>2){
			D(L[i],R[i]);
			C(i);
		}
}

inline int query(int x,int y){
	int l=bl[x],r=bl[y];
	int res=0;
	if(l==r){
		for(int i=x;i<=y;++i) res+=a[i];
		return res;
	}
	for(int i=x;i<=R[l];++i) res+=a[i];
	for(int i=L[r];i<=y;++i) res+=a[i];
	for(int i=l+1;i<=r-1;++i) res+=v[i];
	return res;
}

signed main(){
	get_d();
	n=read(),m=read();
	sz=sqrt(n);
	for(int i=1;i<=n;++i){
		a[i]=read();
		bl[i]=(i-1)/sz+1;
		if(bl[i]!=bl[i-1]) L[bl[i]]=i,R[bl[i-1]]=i-1;
	}
	R[bl[n]]=n;
	build();
	while(m--){
		int op=read(),x=read(),y=read();
		if(op==1) update(x,y);
		else printf("%lld\n",query(x,y));
	}
}
posted @ 2022-07-11 20:07  Into_qwq  阅读(45)  评论(0)    收藏  举报