CF438D 线段树 区间求和,区间求膜,单点更新

题目链接

题目大意:

给定一个长度为n的序列,要求能够执行m次下列操作:

1.查询区间[l,r]的和

2.将区间[l,r]的每一个数%=mod

3.修改第x个数为y

操作1,3都是线段树的基本操作,线段树详细知识可以看看这篇大牛的文章   https://www.cnblogs.com/TheRoadToTheGold/p/6254255.html

操作二取模如果一个个模那么复杂度为O(n*m),直接T,我们可以在线段树中同时维护一个最大值,如果一个区间的最大值比取模值要小,就可以不取模,否则的话递归左右子树,继续将每个区间

的最大值与取模值进行比较,一直不断缩小到单点,使需要取模的单点才取模,这样就不会T了

代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int inf=1<<30;
 4 typedef long long ll;
 5 const double pi=acos(-1);
 6 const int mod=1e9+7;
 7 const int maxn=1e5+7;
 8 int n,m;ll ans;
 9 struct node{
10     int l,r,maxx;ll v;
11 }tree[4*maxn];
12 void modify(int k,int x,int y,int z){
13     if(tree[k].maxx<z) return ;
14     if(tree[k].l==tree[k].r){
15         tree[k].v%=z;tree[k].maxx=tree[k].v;
16         return ;
17     }
18     int m=(tree[k].l+tree[k].r)/2;
19     if(x<=m) modify(2*k,x,y,z);
20     if(y>m) modify(2*k+1,x,y,z);
21     tree[k].v=tree[k*2].v+tree[2*k+1].v;
22     tree[k].maxx=max(tree[k*2].maxx,tree[k*2+1].maxx);
23 }
24 void build(int l,int r,int k){
25     //important
26     tree[k].l=l,tree[k].r=r;
27     if(l==r){
28         scanf("%d",&tree[k].v);
29         tree[k].maxx=tree[k].v;
30         return ;
31     }
32     int m=(l+r)>>1;
33     build(l,m,k*2);
34     build(m+1,r,k*2+1);
35     tree[k].v=tree[2*k].v+tree[2*k+1].v;
36     tree[k].maxx=max(tree[2*k].maxx,tree[2*k+1].maxx);
37 }
38 void sum(int k,int x,int y){
39     if(tree[k].l>=x&&tree[k].r<=y){
40         ans+=tree[k].v;    //cout<<111<<endl;
41         return ;
42     }
43     int m=(tree[k].l+tree[k].r)/2;
44     if(x<=m) sum(k*2,x,y);
45     if(y>m) sum(k*2+1,x,y);
46 }
47 void change(int k,int x,int y){
48     if(tree[k].l==tree[k].r){
49         tree[k].v=y,tree[k].maxx=y;return;
50     }
51     int m=(tree[k].l+tree[k].r)/2;
52     if(x<=m) change(k*2,x,y);
53     else change(k*2+1,x,y);
54     tree[k].v=tree[2*k].v+tree[2*k+1].v;
55     tree[k].maxx=max(tree[2*k].maxx,tree[2*k+1].maxx);
56 }
57 int main(){
58     scanf("%d%d",&n,&m);
59     build(1,n,1);
60     while(m--){
61         int type,x,y,z;scanf("%d%d%d",&type,&x,&y);
62         if(type==1){
63             ans=0;
64             sum(1,x,y);
65             printf("%lld
",ans);
66         }
67         else if(type==2){
68             scanf("%d",&z);
69             modify(1,x,y,z);
70         }
71         else if(type==3){
72             change(1,x,y);
73         }
74     }
75     return 0;
76 }
原文地址:https://www.cnblogs.com/qingjiuling/p/10393209.html