洛谷 CF438D The Child and Sequence(線段樹)
阿新 • • 發佈:2021-09-16
傳送門
解題思路
直接用線段樹維護取模是不好維護的。
而且我們發現一個數x最多取模logx次(每次大小減半),所以可以暴力取模。
維護的資訊除了區間和,還有區間最大值,因為當區間最大值<模數時,此操作是無效的。
AC程式碼
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn=1e5+5; int n,m; struct node{ long long max,sum; }d[maxn*4]; inline void pushup(int id){ d[id].max=max(d[id*2].max,d[id*2+1].max); d[id].sum=d[id*2].sum+d[id*2+1].sum; } void update(int id,int l,int r,int x,int v){ if(l==r){ d[id].sum=d[id].max=v; return; } int mid=(l+r)/2; if(x<=mid) update(id*2,l,mid,x,v); else update(id*2+1,mid+1,r,x,v); pushup(id); } long long query(int id,int l,int r,int x,int y){ if(x<=l&&r<=y){ return d[id].sum; } int mid=(l+r)/2; long long res=0; if(x<=mid) res+=query(id*2,l,mid,x,y); if(y>mid) res+=query(id*2+1,mid+1,r,x,y); return res; } void update_mod(int id,int l,int r,int x,int y,long long mod){ if(d[id].max<mod) return; if(l==r){ d[id].sum%=mod; d[id].max%=mod; return; } int mid=(l+r)/2; if(x<=mid&&d[id*2].max>=mod) update_mod(id*2,l,mid,x,y,mod); if(y>mid&&d[id*2+1].max>=mod) update_mod(id*2+1,mid+1,r,x,y,mod); pushup(id); } int main(){ ios::sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=n;i++){ int a; cin>>a; update(1,1,n,i,a); } for(int i=1;i<=m;i++){ int tp; cin>>tp; if(tp==1){ int l,r; cin>>l>>r; cout<<query(1,1,n,l,r)<<endl; continue; } if(tp==2){ int l,r; long long x; cin>>l>>r>>x; update_mod(1,1,n,l,r,x); continue; } if(tp==3){ int k,x; cin>>k>>x; update(1,1,n,k,x); continue; } } return 0; }