【题目描述】
给定一个长度为 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。第二行 n 个整数 a[1]~a[n]。接下来 m 行每
行 3 或 4 个整数表示操作。
【输出数据】
对于每个操作 1,输出一行一个整数表示答案。
【样例输入】
5 5
1 2 3 4 5
2 3 5 4
3 3 5
1 2 5
2 1 3 3
1 1 3
【样例输出】
8
5【数据范围】
对于 40%的数据,n,m<=1000。
对于 100%的数据, n,m<=100000,
1<=l<=r<=n,
1<=k<=n,
1<=x<=10^9,
0<=a[i],y<=10^9。
用线段树维护区间最大值以及区间和。
进行取模操作时,如果 x>区间最大值那么退出,否则两
边都递归下去。
单个数被有效地取模一次只会花费 O(logn)的时间,并且
数值至少减半,因此每次修改至多使时间复杂度增加
O(logn^2)。
时间复杂度 O(mlogn^2)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long lol; 7 lol a[100001],c[400001],s[400001]; 8 int n,m,opt; 9 void build(int rt,int l,int r) 10 { 11 if (l==r) 12 { 13 c[rt]=a[l]; 14 s[rt]=a[l]; 15 return; 16 } 17 int mid=(l+r)/2; 18 build(rt*2,l,mid); 19 build(rt*2+1,mid+1,r); 20 c[rt]=max(c[rt*2],c[rt*2+1]); 21 s[rt]=s[rt*2]+s[rt*2+1]; 22 } 23 void update(int rt,int l,int r,int L,int R,lol d) 24 { 25 if (l==r) 26 { 27 c[rt]=c[rt]%d; 28 s[rt]%=d; 29 return; 30 } 31 if (l>=L&&r<=R) 32 { 33 if (c[rt]<d) 34 return; 35 } 36 int mid=(l+r)/2; 37 if (L<=mid) update(rt*2,l,mid,L,R,d); 38 if (R>mid) update(rt*2+1,mid+1,r,L,R,d); 39 c[rt]=max(c[rt*2],c[rt*2+1]); 40 s[rt]=s[rt*2]+s[rt*2+1]; 41 } 42 lol query(int rt,int l,int r,int L,int R) 43 { 44 if (l>=L&&r<=R) 45 { 46 return s[rt]; 47 } 48 int mid=(l+r)/2; 49 lol sum=0; 50 if (L<=mid) sum+=query(rt*2,l,mid,L,R); 51 if (R>mid) sum+=query(rt*2+1,mid+1,r,L,R); 52 return sum; 53 } 54 void change(int rt,int l,int r,int x,lol d) 55 { 56 if (l==r) 57 { 58 c[rt]=d; 59 s[rt]=d; 60 return; 61 } 62 int mid=(l+r)/2; 63 if (x<=mid) change(rt*2,l,mid,x,d); 64 else change(rt*2+1,mid+1,r,x,d); 65 c[rt]=max(c[rt*2],c[rt*2+1]); 66 s[rt]=s[rt*2]+s[rt*2+1]; 67 } 68 int main() 69 {lol d; 70 int i,j,l,r,k; 71 cin>>n>>m; 72 for (i=1;i<=n;i++) 73 scanf("%lld",&a[i]); 74 build(1,1,n); 75 for (i=1;i<=m;i++) 76 { 77 scanf("%d",&opt); 78 if (opt==1) 79 { 80 scanf("%d%d",&l,&r); 81 printf("%lld\n",query(1,1,n,l,r)); 82 } 83 else if (opt==2) 84 { 85 scanf("%d%d%lld",&l,&r,&d); 86 update(1,1,n,l,r,d); 87 } 88 else if (opt==3) 89 { 90 scanf("%d%lld",&k,&d); 91 change(1,1,n,k,d); 92 } 93 } 94 }