【题目描述】

给定一个长度为 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 }