#线段树#CF438D The Child and Sequence

题目

支持区间求和,区间取模,单点修改


分析

首先区间取模一直不停取模最多log次是有效的,
所以处理区间最大值,若区间最大值小于模数直接退出,否则暴力修改
时间复杂度\(O(mlog^2n)\)


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=100011; typedef long long lll;
int a[N],mx[N<<2],n,m; lll w[N<<2];
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans;
}
inline void print(lll ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline signed max(int a,int b){return a>b?a:b;}
inline void pup(int k){
	w[k]=w[k<<1]+w[k<<1|1],
	mx[k]=max(mx[k<<1],mx[k<<1|1]);	
}
inline void build(int k,int l,int r){
	if (l==r) {
	    w[k]=mx[k]=a[l];
	    return;
	}
	rr int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	pup(k);
}
inline void change(int k,int l,int r,int x,int z){
	if (l==r){
		w[k]=mx[k]=z;
		return;
	}
	rr int mid=(l+r)>>1;
	if (x<=mid) change(k<<1,l,mid,x,z);
	    else change(k<<1|1,mid+1,r,x,z);
	pup(k);
}
inline void update(int k,int l,int r,int x,int y,int z){
	if (mx[k]<z) return;
	if (l==r){
		w[k]%=z,mx[k]%=z;
		return;
	}
	rr int mid=(l+r)>>1;
	if (x<=mid) update(k<<1,l,mid,x,y,z);
	if (y>mid) update(k<<1|1,mid+1,r,x,y,z);
	pup(k);
}
inline lll query(int k,int l,int r,int x,int y){
	if (l==x&&r==y) return w[k];
	rr int mid=(l+r)>>1;
	if (y<=mid) return query(k<<1,l,mid,x,y);
	else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
	else return query(k<<1,l,mid,x,mid)+query(k<<1|1,mid+1,r,mid+1,y);
}
signed main(){
    n=iut(); m=iut();
    for (rr int i=1;i<=n;++i) a[i]=iut();
    build(1,1,n);
    for (rr int z,x,y;m;--m){
    	z=iut(),x=iut(),y=iut();
    	if (z==1) print(query(1,1,n,x,y)),putchar(10);
    	    else if (z==3) change(1,1,n,x,y);
    	        else update(1,1,n,x,y,iut()); 
	}
	return 0;
}
posted @ 2020-10-03 01:42  lemondinosaur  阅读(45)  评论(0编辑  收藏  举报