給定數列,區間查詢和,區間取模,單點修改。node
n,m小於10^5c++
難點在於區間取模,相似於區間開方,若是這個區間的最大值$<=$ $mod$,不對其進行操做,反之對區間裏每一個數進行操做(因爲操做數不多)ui
開$long long$spa
#include<bits/stdc++.h> #define N 1000000 #define LL long long using namespace std; struct node{ LL l,r,w,f,maxn; }tr[N]; void push_up(LL k){ tr[k].maxn=max(tr[k<<1].maxn,tr[k<<1|1].maxn); tr[k].w=tr[k<<1].w+tr[k<<1|1].w; } void build(LL k,LL l,LL r){ tr[k].l=l,tr[k].r=r; if(l==r){ scanf("%d",&tr[k].w); tr[k].maxn=tr[k].w; return; } LL mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); push_up(k); } void push_down(LL k){ if(tr[k].f){ tr[k<<1].w+=tr[k].f*(tr[k<<1].r-tr[k<<1].l+1); tr[k<<1].f+=tr[k].f,tr[k<<1].maxn+tr[k].f; tr[k<<1|1].w+=tr[k].f*(tr[k<<1|1].r-tr[k<<1|1].l+1); tr[k<<1|1].f+=tr[k].f,tr[k<<1|1].maxn+tr[k].f; tr[k].f=0; } } void change(LL k,LL ql,LL qr,LL Mod,LL x){ LL l=tr[k].l,r=tr[k].r,mid=(l+r)>>1; if(l==r){ if(!Mod) tr[k].w=tr[k].maxn=x; else tr[k].w%=Mod,tr[k].maxn=tr[k].w; return; }push_down(k); if(ql<=mid&&tr[k<<1].maxn>=Mod) change(k<<1,ql,qr,Mod,x); if(qr>mid&&tr[k<<1|1].maxn>=Mod) change(k<<1|1,ql,qr,Mod,x); push_up(k); } LL query(LL k,LL ql,LL qr){ LL l=tr[k].l,r=tr[k].r,mid=(l+r)>>1; if(ql<=l&&qr>=r) return tr[k].w; push_down(k); LL ans=0; if(ql<=mid) ans+=query(k<<1,ql,qr); if(qr>mid) ans+=query(k<<1|1,ql,qr); push_up(k); return ans; } LL n,m; int main() { scanf("%lld%lld",&n,&m); build(1,1,n); for(LL opt,l,r,x,i=1;i<=m;i++){ scanf("%lld%lld%lld",&opt,&l,&r); if(opt==1){ printf("%lld\n",query(1,l,r)); }else if(opt==2){ scanf("%lld",&x); change(1,l,r,x,0); }else if(opt==3){ change(1,l,l,0,r); } } return 0; }