【原题题面】传送门
【大致题意】
- 给定一个长度为n的非负整数序列a,你需要支持以下操作:
- 1:给定l,r,输出a[l]+a[l+1]+…+a[r]。
- 2:给定l,r,x,将a[l],a[l+1],…,a[r]对x取模。
- 3:给定k,y,将a[k]修改为y。
【数据范围】
n,m<=100000,a[i],x,y<=109。
【题解大意】
维护最大值和区间和,然后通过最大值有没有超过x来判断需不需要取模操作。
【code】
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define rep(k,i,j) for(int k = i;k <= j; ++k) #define FOR(k,i,j) for(int k = i;k >= j; --k) inline int read(){ int x = 0,f = 1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();} return x*f; } const int N=100010; int n,q,a[N]; int ty,l,r,x,k; int t[N<<2];//max long long s[N<<2];//sum void B(int l,int r,int p) { if(l==r){s[p]=t[p]=a[l];return;} int m=l+r>>1; B(l,m,p<<1),B(m+1,r,p<<1|1); t[p]=max(t[p<<1],t[p<<1|1]); s[p]=s[p<<1]+s[p<<1|1]; } long long A(int l,int r,int p,int L,int R) { if(L<=l&&r<=R)return s[p]; int m=l+r>>1; long long as=0; if(L<=m)as+=A(l,m,p<<1,L,R); if(R>m)as+=A(m+1,r,p<<1|1,L,R); return as; } void M(int l,int r,int p,int L,int R,int x) { if(l==r){s[p]=t[p]%=x;return;} int m=l+r>>1; if(L<=m&&t[p<<1]>=x)M(l,m,p<<1,L,R,x); if(R>m&&t[p<<1|1]>=x)M(m+1,r,p<<1|1,L,R,x); t[p]=max(t[p<<1],t[p<<1|1]); s[p]=s[p<<1]+s[p<<1|1]; } void U(int l,int r,int p,int k,int x) { if(l==r){s[p]=t[p]=x;return;} int m=l+r>>1; if(k<=m)U(l,m,p<<1,k,x); else U(m+1,r,p<<1|1,k,x); t[p]=max(t[p<<1],t[p<<1|1]); s[p]=s[p<<1]+s[p<<1|1]; } int main() { n=read(),q=read(); for(int i=1;i<=n;++i)a[i]=read(); B(1,n,1); for(int i=1;i<=q;++i) { ty=read(); if(ty==1) { l=read(),r=read(); printf("%lld\n",A(1,n,1,l,r)); } if(ty==2) { l=read(),r=read(),x=read(); M(1,n,1,l,r,x); } if(ty==3) { k=read(),x=read(); U(1,n,1,k,x); } } return 0; }