CF438D The Child and Sequence

CF438D The Child and Sequence

题意:给定一个序列,支持三种操作;
1,单点修改
2,区间查询
3,区间取模
难点在于区间取模,思考使一个数取模变为1时间复杂度是log的,因此记录一个最大值,当模数<=最大值时,暴力取模;

#include<iostream>
#include<cstdio>
#define l(o) (o<<1)
#define r(o) ((o<<1)|1)
#define mid ((l+r)>>1)
#define LL long long
using namespace std;
const int N=1e5+7;
int n,m,ans;
LL a[N],sum[N<<2],maxn[N<<2];

void up(int o){
	sum[o]=sum[l(o)]+sum[r(o)];
	maxn[o]=max(maxn[l(o)],maxn[r(o)]);
}

void build(int o,int l,int r){
	if(l==r){
		scanf("%d",&sum[o]);
		maxn[o]=sum[o];
		return;
	}
	build(l(o),l,mid);
	build(r(o),mid+1,r);
	up(o);
}

void change(int o,int l,int r,int k,int val){
	if(l==r){
		sum[o]=maxn[o]=val;
		return;
	}
	if(k<=mid) change(l(o),l,mid,k,val);
	if(k>mid) change(r(o),mid+1,r,k,val);
	up(o);
}

void cmod(int o,int l,int r,int L,int R,int p){
	if(maxn[o]<p) return;
	if(l==r){
		sum[o]%=p;
		maxn[o]%=p;
		return;
	}
	if(L<=mid) cmod(l(o),l,mid,L,R,p);
	if(R>mid) cmod(r(o),mid+1,r,L,R,p);
	up(o);
}

LL ask(int o,int l,int r,int L,int R){
	if(L<=l&&R>=r){
		return sum[o];
	}
	LL res=0;
	if(L<=mid) res=ask(l(o),l,mid,L,R);
	if(R>mid) res+=ask(r(o),mid+1,r,L,R);
	return res;
}

int main(){
	scanf("%d%d",&n,&m);
//	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int x,y,opt,val;
		scanf("%d%d%d",&opt,&x,&y);
		if(opt==1){
			cout<<1LL*ask(1,1,n,x,y)<<"\n";
		}
		if(opt==2){
			scanf("%d",&val);
			cmod(1,1,n,x,y,val);
		}
		if(opt==3){
			change(1,1,n,x,y);
		}
	}
}
上一篇:QuantLib 金融计算——修复 BatesProcess 中的两个 Bug


下一篇:线段树+由%加快(CF438D The Child and Sequence