CF438D The Child and Sequence(线段树)

区间求和,单点修改,单点取模。

单点取模直接暴力取模,存一个max,如果max<mod,那么无需取模。

#include<cstdio>
#include<iostream>
using namespace std;
const int N=100005;
typedef long long ll;
int n,m;
struct node{
	int max;
	ll sum;
}t[N<<2];
int a[N];
int read(){
	int num=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		num=num*10+c-'0';
		c=getchar();
	}
	return f*num;
}
void pushup(int k){
	t[k].max=max(t[k<<1].max,t[k<<1|1].max);
	t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
}
void build(int k,int l,int r){
	if(l==r){
		t[k].max=t[k].sum=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	pushup(k);
}
ll query(int k,int l,int r,int x,int y){
	if(x<=l&&r<=y){
		return t[k].sum;
	}
	int mid=(l+r)>>1;
	ll res=0;
	if(x<=mid) res+=query(k<<1,l,mid,x,y);
	if(y>mid) res+=query(k<<1|1,mid+1,r,x,y);
	return res;
}
void update(int k,int l,int r,int x,int y,int mod){
	if(t[k].max<mod) return;
	if(l==r){
		t[k].sum%=mod;
		t[k].max%=mod;
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid&&t[k<<1].max>=mod) update(k<<1,l,mid,x,y,mod);
	if(y>mid&&t[k<<1|1].max>=mod) update(k<<1|1,mid+1,r,x,y,mod);
	pushup(k);
}
void change(int k,int l,int r,int x,int v){
	if(l==r){
		t[k].sum=t[k].max=v;
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid) change(k<<1,l,mid,x,v);
	if(x>mid) change(k<<1|1,mid+1,r,x,v);
	pushup(k);
}
int main(){
	n=read(); m=read();
	for(int i=1;i<=n;i++) a[i]=read();
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int type=read();
		if(type==1){
			int l=read(),r=read();
			printf("%lld\n",query(1,1,n,l,r));
		}
		else if(type==2){
			int l=read(),r=read(),x=read();
			update(1,1,n,l,r,x);
		}
		else{
			int l=read(),x=read();
			change(1,1,n,l,x);
		}
	}
	return 0;
}
posted @ 2021-09-26 14:40  dfydn  阅读(24)  评论(0编辑  收藏  举报