分块练习

分块练习#

P4109 定价#

思路

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

1e5 个数字分成一块,1105 结果为 5a105+1(a+1)105 结果为 (a+1)105

这样可以分成 104 个块,每次查询就是 O(105)

总时间复杂度为 O(T105)

可以通过本题

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)=1d(2)=2,因此当一个区间内所有的数都 2 的时候修改操作就没有了意义

因为对于 xd(x)2x

所以暴力修改序列的话复杂度是 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));
	}
}

作者:Into_qwq

出处:https://www.cnblogs.com/into-qwq/p/16467701.html

版权:本作品采用「qwq」许可协议进行许可。

posted @   Into_qwq  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示