线段树模板2 洛谷p3373

题目链接:https://www.luogu.com.cn/problem/P3373

本题思路主要也是借鉴了洛谷题解区的方法

通过建立两个标签,tag1用于加法记忆,tag2用于乘法记忆

关键是注意两个运算标签的处理 当个简单模板康康

  1 #include<bits/stdc++.h>
2 #define ll long long 3 using namespace std; 4 const int maxn=1e5+10;
5 int n,w,m; 6 int temp[4*maxn];
7 struct Segment_Tree 8 { 9 ll val; 10 ll tag1; 11 ll tag2; 12 }data[maxn*4];
13 inline void push_up(int root) 14 { 15   data[root].val=(data[root<<1].val+data[root<<1|1].val)%m; 16 }
17 void build(int left,int right,int root)//root为线段树下标,left为数组下标 18 { 19   data[root].tag1=0; 20   data[root].tag2=1; 21   if(left == right){ 22     data[root].val=temp[left]; 23     return ; 24   } 25   int mid=(left+right)>>1; 26   build(left,mid,root<<1); 27   build(mid+1,right,root<<1|1); 28   data[root].val=data[root<<1].val+data[root<<1|1].val; 29   data[root].val%=m; 30 } 31 32 inline void push_down(int left,int right,int root) 33 { 34   int mid=(left+right)>>1; 35   data[root<<1].val=(data[root<<1].val*data[root].tag2+(mid-left+1)*data[root].tag1)%m; 36   data[root<<1|1].val=(data[root<<1|1].val*data[root].tag2+(right-mid)*data[root].tag1)%m; 37   data[root<<1].tag2=(data[root].tag2*data[root<<1].tag2)%m; 38   data[root<<1|1].tag2=(data[root].tag2*data[root<<1|1].tag2)%m; 39   data[root<<1].tag1=(data[root<<1].tag1*data[root].tag2+data[root].tag1)%m; 40   data[root<<1|1].tag1=(data[root<<1|1].tag1*data[root].tag2+data[root].tag1)%m; 41   data[root].tag1=0; 42   data[root].tag2=1; 43 }
44 void add(int left,int right,int root,int x,int y,int v) 45 { 46   if(x > right || y < left) return ; 47   if(x <= left && y >= right){//注意符号 48     data[root].val=(data[root].val+(right-left+1)*v)%m; 49     data[root].tag1=(data[root].tag1+v)%m; 50     return ; 51   }
52   push_down(left,right,root); 53   int mid=(left+right)>>1; 54   add(left,mid,root<<1,x,y,v); 55   add(mid+1,right,root<<1|1,x,y,v); 56   push_up(root);// 57 }
58 void multiply(int left,int right,int root,int x,int y,int v) 59 { 60   if(x > right || y < left) return ; 61   if(x <= left && y >= right){ 62     data[root].val=(data[root].val*v)%m; 63     data[root].tag2=(data[root].tag2*v)%m; 64     data[root].tag1=(data[root].tag1*v)%m;//加的也要乘 65     return ; 66   } 67   push_down(left,right,root); 68   int mid=(left+right)>>1; 69   multiply(left,mid,root<<1,x,y,v); 70   multiply(mid+1,right,root<<1|1,x,y,v); 71   push_up(root); 72 }
73 ll query(int left,int right,int root,int x,int y) 74 { 75   if(x > right || y < left) return 0; 76   if(x <= left && y >= right){ 77     return data[root].val; 78   } 79   int mid=(left+right)>>1; 80   push_down(left,right,root); 81   return (query(left,mid,root<<1,x,y)+query(mid+1,right,root<<1|1,x,y))%m; 82 }
83 int main(){ 84   cin >> n >> w >> m; 85   for(int i = 1 ; i <= n ; i++){ 86     cin >> temp[i]; 87   } 88   build(1,n,1); 89   int flag,a,b,v; 90   for(int i = 1 ; i <= w ; i++){ 91     scanf("%d",&flag); 92     if(flag == 1){ 93       scanf("%d%d%d",&a,&b,&v); 94       multiply(1,n,1,a,b,v); 95     }else if(flag == 2){ 96       scanf("%d%d%d",&a,&b,&v); 97       add(1,n,1,a,b,v); 98     }else{ 99       scanf("%d%d",&a,&b); 100       printf("%lld ",query(1,n,1,a,b)%m); 101     } 102   } 103   return 0; 104 } 105 106
原文地址:https://www.cnblogs.com/ecustlegendn324/p/12310909.html