把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF438D The Child and Sequence

题面传送门
明显势能线段树。
这里证明一下取模的下界。
对于一个数\(x\),若取模的数\(y>\frac{x}{2}\),那么\(x\%y=x-y<\frac{x}{2}\),若取模的数\(y<\frac{x}{2}\),那么\(x\%y<y<\frac{x}{2}\),则一个数至多取模\(logn\)次就会为\(1\)
修改至多会增加\(logn\)次取模,也不影响复杂度。
均摊时间复杂度\(O(logn)\)
代码实现:

#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int n,m,k,x,y,a[100039],z,sx,sum[400039];
long long f[400039];
inline void jianshu(int l,int r,int now){
	if(l==r) {f[now]=a[l];sum[now]=a[l];return;}
	int m=(l+r)>>1;
	jianshu(l,m,now<<1);jianshu(m+1,r,now<<1|1);
	f[now]=f[now<<1]+f[now<<1|1];
	sum[now]=max(sum[now<<1],sum[now<<1|1]);
}
inline long long find(int l,int r,int now){
	if(x<=l&&r<=y)return f[now];
	int m=(l+r)>>1;
	long long fs=0;
	if(x<=m) fs+=find(l,m,now<<1);
	if(y>m) fs+=find(m+1,r,now<<1|1);
	return fs;
}
inline void add(int l,int r,int now){
	if(l==r) {f[now]%=z;sum[now]=f[now];return;}
	int m=(l+r)>>1;
	if(x<=m&&sum[now<<1]>=z) add(l,m,now<<1);
	if(y>m&&sum[now<<1|1]>=z) add(m+1,r,now<<1|1);
	f[now]=f[now<<1]+f[now<<1|1];
	sum[now]=max(sum[now<<1],sum[now<<1|1]);
}
inline void get(int l,int r,int now){
	if(l==r) {f[now]=z,sum[now]=z;return;}
	int m=(l+r)>>1;
	if(x<=m) get(l,m,now<<1);
	else get(m+1,r,now<<1|1);
	f[now]=f[now<<1]+f[now<<1|1];
	sum[now]=max(sum[now<<1],sum[now<<1|1]);
}
int main(){
	register int i;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++) scanf("%d",&a[i]);
	jianshu(1,n,1);
	for(i=1;i<=m;i++){
		scanf("%d",&sx);
		if(sx==1){
			scanf("%d%d",&x,&y);
			printf("%lld\n",find(1,n,1));
		}
		if(sx==2){
			scanf("%d%d%d",&x,&y,&z);
			add(1,n,1);
		}
		if(sx==3){
			scanf("%d%d",&x,&z);
			get(1,n,1);
		}
	}
}//
posted @ 2020-06-13 19:59  275307894a  阅读(64)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end