CF438D The Child and Sequence
Posted song-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF438D The Child and Sequence相关的知识,希望对你有一定的参考价值。
CF438D The Child and Sequence
给定数列,区间查询和,区间取模,单点修改。
n,m小于10^5
难点在于区间取模,类似于区间开方,如果这个区间的最大值$<=$ $mod$,不对其进行操作,反之对区间里每个数进行操作(由于操作数很少)
开$long long$
#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 ",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; }
以上是关于CF438D The Child and Sequence的主要内容,如果未能解决你的问题,请参考以下文章
CF438D The Child and Sequence 线段树
CF438D The Child and Sequence(线段树)