洛谷 P3373 【模板】线段树 2

题目传送门

本题相对于模板1多了乘法,但是代码里面加入了要考虑优先级的因素,所以并不是很好写.

AC代码:

  1 #include<cstdio>
  2 #include<iostream>
  3 
  4 using namespace std;
  5 
  6 int n,m,p;
  7 long long a[100001];
  8 struct kkk {
  9     long long v,mul,add;
 10 }e[400005]; 
 11 
 12 inline void build(int bh,int l,int r) {
 13     e[bh].mul = 1;
 14     e[bh].add = 0;
 15     if(l == r) {
 16         e[bh].v = a[l] % p;
 17         return ;    
 18     }
 19     int mid = l + r >> 1;
 20     build(bh * 2,l,mid);
 21     build(bh * 2 + 1,mid + 1,r);
 22     e[bh].v = e[bh*2].v + e[bh*2+1].v;
 23     e[bh].v %= p;
 24     return ;
 25 }
 26 
 27 inline void pushdown(int bh,int l,int r) {
 28     int mid = (l + r) >> 1;
 29     e[bh*2].v = (e[bh*2].v * e[bh].mul + e[bh].add * (mid - l + 1)) % p;
 30     e[bh*2+1].v = (e[bh*2+1].v * e[bh].mul + e[bh].add * (r - mid)) % p;
 31     e[bh*2].mul = (e[bh*2].mul * e[bh].mul) % p;
 32     e[bh*2+1].mul = (e[bh*2+1].mul * e[bh].mul) % p;
 33     e[bh*2].add = (e[bh*2].add * e[bh].mul + e[bh].add) % p;
 34     e[bh*2+1].add = (e[bh*2+1].add * e[bh].mul + e[bh].add) % p;
 35     e[bh].mul = 1;
 36     e[bh].add = 0;
 37     return ;
 38 }
 39 
 40 inline void update_Multiply(int bh,int ll,int rr,int l,int r,long long _v) {
 41     if(r < ll || l > rr)
 42         return ;
 43     if(l <= ll && r >= rr) {
 44         e[bh].v = (e[bh].v * _v) % p;
 45         e[bh].mul = (e[bh].mul * _v) % p;
 46         e[bh].add = (e[bh].add * _v) % p;
 47         return ; 
 48     }    
 49     pushdown(bh,ll,rr);
 50     int mid = (ll + rr) >> 1;
 51     update_Multiply(bh * 2,ll,mid,l,r,_v);
 52     update_Multiply(bh * 2 + 1,mid + 1,rr,l,r,_v);
 53     e[bh].v = (e[bh*2].v + e[bh*2+1].v) % p;
 54     return ;
 55 }
 56 
 57 inline void update_Plus(int bh,int ll,int rr,int l,int r,long long _v) {
 58     if(r < ll || rr < l)
 59         return ;
 60     if(l <= ll && r >= rr) { 
 61         e[bh].add = (e[bh].add + _v) % p;
 62         e[bh].v = (e[bh].v + _v * (rr - ll + 1)) % p;
 63         return ;
 64     }
 65     pushdown(bh,ll,rr);
 66     int mid = (ll + rr) >> 1;
 67     update_Plus(bh * 2,ll,mid,l,r,_v);
 68     update_Plus(bh * 2 + 1,mid + 1,rr,l,r,_v);
 69     e[bh].v = (e[bh*2].v + e[bh*2+1].v) % p;
 70     return ;
 71 } 
 72 
 73 long long query(int bh,int ll,int rr,int l,int r) {
 74     if(r < ll || l > rr) 
 75         return 0;
 76     if(l <= ll && r >= rr)
 77         return e[bh].v;
 78     pushdown(bh,ll,rr);
 79     int mid = (ll + rr) >> 1;
 80     return (query(bh * 2,ll,mid,l,r) + query(bh * 2 + 1,mid + 1,rr,l,r)) % p;
 81 }
 82 
 83 int main()
 84 {
 85     scanf("%d%d%d",&n,&m,&p);
 86     for(int i = 1;i <= n; i++)
 87         scanf("%lld",&a[i]);
 88     build(1,1,n);
 89     while(m--) {
 90         int u,x,y;
 91         long long k;
 92         scanf("%d",&u);
 93         if(u == 1) {
 94             scanf("%d%d%lld",&x,&y,&k);
 95             update_Multiply(1,1,n,x,y,k);
 96         }
 97         if(u == 2) {
 98             scanf("%d%d%lld",&x,&y,&k);
 99             update_Plus(1,1,n,x,y,k);
100         }
101         if(u == 3) {
102             scanf("%d%d",&x,&y);
103             printf("%lld\n",query(1,1,n,x,y) % p);
104         }
105     }
106     return 0;
107 }
线段树乘法

 

 

posted @ 2019-08-03 21:02  Mr^Simon  阅读(101)  评论(0编辑  收藏  举报