把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

模板:线段树(2)——加法,乘法,求和

https://www.luogu.org/problemnew/show/P3373

 区间加法乘法修改,区间查询

  1 #include<iostream>
  2 #include<cstdio>
  3 using namespace std;
  4 int p;
  5 long long a[100005];
  6 struct node{
  7     long long v, mul, add;
  8 }st[500005];
  9 void bt(int root, int l, int r){
 10 //初始化lazytag
 11     st[root].mul=1;
 12     st[root].add=0;
 13     if(l==r){
 14         st[root].v=a[l];
 15     }
 16     else{
 17         int m=(l+r)/2;
 18         bt(root*2, l, m);
 19         bt(root*2+1, m+1, r);
 20         st[root].v=st[root*2].v+st[root*2+1].v;
 21     }
 22     st[root].v%=p;
 23     return ;
 24 }
 25 void pushdown(int root, int l, int r){
 26     int m=(l+r)/2;
 27 //儿子的值=此刻儿子的值*爸爸的乘法lazytag+儿子的区间长度*爸爸的加法lazytag
 28     st[root*2].v=(st[root*2].v*st[root].mul+st[root].add*(m-l+1))%p;
 29     st[root*2+1].v=(st[root*2+1].v*st[root].mul+st[root].add*(r-m))%p;
 30     st[root*2].mul=(st[root*2].mul*st[root].mul)%p;
 31     st[root*2+1].mul=(st[root*2+1].mul*st[root].mul)%p;
 32     st[root*2].add=(st[root*2].add*st[root].mul+st[root].add)%p;
 33     st[root*2+1].add=(st[root*2+1].add*st[root].mul+st[root].add)%p;
 34 //把父节点的值初始化
 35     st[root].mul=1;
 36     st[root].add=0;
 37     return ;
 38 }
 39 //乘法,stdl此刻, l给出的
 40 void ud1(int root, int stdl, int stdr, int l, int r, long long k){
 41     if(r<stdl || stdr<l){
 42         return ;
 43     }
 44     if(l<=stdl && stdr<=r){
 45         st[root].v=(st[root].v*k)%p;
 46         st[root].mul=(st[root].mul*k)%p;
 47         st[root].add=(st[root].add*k)%p;
 48         return ;
 49     }
 50     pushdown(root, stdl, stdr);
 51     int m=(stdl+stdr)/2;
 52     ud1(root*2, stdl, m, l, r, k);
 53     ud1(root*2+1, m+1, stdr, l, r, k);
 54     st[root].v=(st[root*2].v+st[root*2+1].v)%p;
 55     return ;
 56 }
 57 //加法
 58 void ud2(int root, int stdl, int stdr, int l, int r, long long k){
 59     if(r<stdl || stdr<l){
 60         return ;
 61     }
 62     if(l<=stdl && stdr<=r){
 63         st[root].add=(st[root].add+k)%p;
 64         st[root].v=(st[root].v+k*(stdr-stdl+1))%p;
 65         return ;
 66     }
 67     pushdown(root, stdl, stdr);
 68     int m=(stdl+stdr)/2;
 69     ud2(root*2, stdl, m, l, r, k);
 70     ud2(root*2+1, m+1, stdr, l, r, k);
 71     st[root].v=(st[root*2].v+st[root*2+1].v)%p;
 72     return ;
 73 }
 74 long long query(int root, int stdl, int stdr, int l, int r){
 75     if(r<stdl || stdr<l){
 76         return 0;
 77     }
 78     if(l<=stdl && stdr<=r){
 79         return st[root].v;
 80     }
 81     pushdown(root, stdl, stdr);
 82     int m=(stdl+stdr)/2;
 83     return (query(root*2, stdl, m, l, r)+query(root*2+1, m+1, stdr, l, r))%p;
 84 }
 85 int main(){
 86     int n, m;
 87     scanf("%d%d%d", &n, &m, &p);
 88     for(int i=1; i<=n; i++){
 89         scanf("%lld", &a[i]);
 90     }
 91     bt(1, 1, n);
 92     for(int i=1; i<=m; i++){
 93         int aha;
 94         scanf("%d", &aha);
 95         int x, y;
 96         long long k;
 97         if(aha==1){
 98             scanf("%d%d%lld", &x, &y, &k);
 99             ud1(1, 1, n, x, y, k);
100         }
101         else if(aha==2){
102             scanf("%d%d%lld", &x, &y, &k);
103             ud2(1, 1, n, x, y, k);
104         }
105         else{
106             scanf("%d%d", &x, &y);
107             printf("%lld\n", query(1, 1, n, x, y));
108         }
109     }
110     return 0;
111 }

 

posted @ 2018-10-26 16:14  AZe-qwq  阅读(190)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end