CF438D The Child and Sequence 线段树
你发现每一次有意义的取模至少会把一个数减半.
所以如果没有赋值操作,每个数最多减半 $log$ 次,复杂度就是 $O(nlog^2n)$ 的.
现在考虑赋值:依次最多只会增加 $O(logn)$ 的时间复杂度,所以复杂度还是 $O(nlog^2n)$ 的.
code:
#include <bits/stdc++.h> #define N 100005 #define inf 12 #define ll long long #define lson now<<1 #define rson now<<1|1 #define setIO(s) freopen(s".in","r",stdin) using namespace std; ll A[N],mx[N<<2]; ll sum[N<<2]; void pushup(int l,int r,int now) { int mid=(l+r)>>1; mx[now]=-inf, sum[now]=0; if(l<=mid) sum[now]+=sum[lson], mx[now]=max(mx[now], mx[lson]); if(r>mid) sum[now]+=sum[rson], mx[now]=max(mx[now], mx[rson]); } void build(int l,int r,int now) { if(l==r) { sum[now]=mx[now]=A[l]; return; } int mid=(l+r)>>1; if(l<=mid) build(l,mid,lson); if(r>mid) build(mid+1,r,rson); pushup(l,r,now); } ll query(int l,int r,int now,int L,int R) { if(l>=L&&r<=R) return sum[now]; ll tmp=0; int mid=(l+r)>>1; if(L<=mid) tmp+=query(l,mid,lson,L,R); if(R>mid) tmp+=query(mid+1,r,rson,L,R); return tmp; } void update(int l,int r,int now,int L,int R,int mod) { if(mx[now]<mod) return; if(l==r) { sum[now]%=mod; mx[now]%=mod; return; } int mid=(l+r)>>1; if(L<=mid) update(l,mid,lson,L,R,mod); if(R>mid) update(mid+1,r,rson,L,R,mod); pushup(l,r,now); } void modify(int l,int r,int now,int p,int v) { if(l==r) { sum[now]=mx[now]=1ll*v; return; } int mid=(l+r)>>1; if(p<=mid) modify(l,mid,lson,p,v); else modify(mid+1,r,rson,p,v); pushup(l,r,now); } int main() { int i,j,n,m; // setIO("input"); scanf("%d%d",&n,&m); for(i=1;i<=n;++i) scanf("%lld",&A[i]); build(1,n,1); for(i=1;i<=m;++i) { int op,l,r,x; scanf("%d",&op); if(op==1) { scanf("%d%d",&l,&r); printf("%lld\n",query(1,n,1,l,r)); } if(op==2) { scanf("%d%d%d",&l,&r,&x); update(1,n,1,l,r,x); } if(op==3) { scanf("%d%d",&l,&x); modify(1,n,1,l,x); } } return 0; }