CF438D The Child and Sequence 线段树
给定数列,区间查询和,区间取模,单点修改。
n,m小于10^5
。。。当区间最值小于模数时,就直接返回就好啦~
#include<cstdio> #include<iostream> #define R register int #define ls (tr<<1) #define rs (tr<<1|1) using namespace std; inline long long g() { register long long ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } int n,m,M; long long sum[400010],mx[400010],cnt[400010]; inline void upd(int tr) {sum[tr]=sum[ls]+sum[rs]; mx[tr]=max(mx[ls],mx[rs]);} inline void build(int tr,int l,int r) { if(l==r) {mx[tr]=sum[tr]=g(); return ;} R md=(l+r)>>1; build(ls,l,md),build(rs,md+1,r); upd(tr); } inline void chg(int tr,int l,int r,int pos,int x) { if(l==r) {sum[tr]=mx[tr]=x; return ;} R md=(l+r)>>1; if(pos>md) chg(rs,md+1,r,pos,x); else chg(ls,l,md,pos,x); upd(tr); } inline void change(int tr,int l,int r,int LL,int RR) { if(mx[tr]<M) return ; if(l==r) {mx[tr]=sum[tr]=sum[tr]%M; return ;} R md=(l+r)>>1; if(LL>md) change(rs,md+1,r,LL,RR); else if(RR<md+1) change(ls,l,md,LL,RR); else change(ls,l,md,LL,md),change(rs,md+1,r,md+1,RR); upd(tr); } inline long long query(int tr,int l,int r,int LL,int RR) { if(l==LL&&r==RR) return sum[tr]; R md=(l+r)>>1; if(LL>md) return query(rs,md+1,r,LL,RR); else if(RR<md+1) return query(ls,l,md,LL,RR); else return query(ls,l,md,LL,md)+query(rs,md+1,r,md+1,RR); } signed main() { n=g(),m=g(); build(1,1,n); for(R i=1,k,l,r;i<=m;++i) { k=g(),l=g(),r=g(); if(k==1) printf("%lld\n",query(1,1,n,l,r)); else if(k==2) M=g(),change(1,1,n,l,r); else chg(1,1,n,l,r); } }
2019.04.18