线段树

别来无恙 提交于 2019-11-28 01:33:26
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 typedef long long ll;
  7 int n , m;
  8 ll mod;
  9 int num[100003];
 10 struct node
 11 {
 12     ll sum , add , mul;
 13 }tree[100003 << 2];
 14 void update(int p)
 15 {
 16     tree[p].sum = (tree[p << 1].sum + tree[p << 1 | 1].sum) % mod;
 17 }
 18 void down(int p , int l , int r)
 19 {
 20     int mid = (l + r) >> 1;
 21     tree[p << 1].sum = ( tree[p << 1].sum * tree[p].mul + tree[p].add * (mid - l + 1) ) % mod;
 22     tree[p << 1 | 1].sum = ( tree[p << 1 | 1].sum * tree[p].mul + tree[p].add * (r - mid) ) % mod;
 23     tree[p << 1].mul = (tree[p << 1].mul * tree[p].mul) % mod;
 24     tree[p << 1 | 1].mul = (tree[p << 1 | 1].mul * tree[p].mul) % mod;
 25     tree[p << 1].add = (tree[p].mul * tree[p << 1].add + tree[p].add) % mod;
 26     tree[p << 1 | 1].add = (tree[p].mul * tree[p << 1 | 1].add + tree[p].add) % mod;
 27     tree[p].mul = 1 , tree[p].add = 0;
 28 }
 29 void Build(int l , int r , int p)
 30 {
 31     tree[p].add = 0 ,tree[p].mul = 1;
 32     if(l == r)
 33     {
 34         tree[p].sum = num[l];
 35         return;
 36     }
 37     int mid = (l + r) >> 1;
 38     Build(l , mid , p << 1);
 39     Build(mid + 1 , r , p << 1 | 1);
 40     update(p);    
 41 }
 42 void Mul(int l , int r , int ll , int rr , int p , int k)
 43 {
 44     if(ll >= l && rr <= r)
 45     {
 46         tree[p].mul = tree[p].mul * k % mod;
 47         tree[p].add = tree[p].add * k % mod;
 48         tree[p].sum = tree[p].sum * k % mod;
 49         return;
 50     }
 51     down(p , ll , rr);
 52     int mid = (ll + rr) >> 1;
 53     if(mid >= l)
 54         Mul(l , r , ll , mid , p << 1 , k);
 55     if(mid < r)
 56         Mul(l , r , mid + 1 , rr , p << 1 | 1 , k);
 57     update(p);
 58 }
 59 void Add(int l , int r , int ll , int rr , int p , int k)
 60 {
 61     if(ll >= l && rr <= r)
 62     {
 63         tree[p].add = (tree[p].add + k) % mod;
 64         tree[p].sum = (tree[p].sum + (rr - ll + 1) * k) % mod;
 65         return;
 66     }
 67     down(p , ll , rr);
 68     int mid = (ll + rr) >> 1;
 69     if(mid >= l)
 70         Add(l , r , ll , mid , p << 1 , k);
 71     if(mid < r)
 72         Add(l , r , mid + 1 , rr , p << 1 | 1 , k);
 73     update(p);
 74 }
 75 ll Query(int l , int r , int ll , int rr , int p)
 76 {
 77     long long ans = 0;
 78     if(ll >= l && rr <= r)
 79         return tree[p].sum;
 80     down(p , ll , rr);
 81     int mid = (ll + rr) >> 1;
 82     if(mid >= l)
 83         ans = (ans + Query(l , r , ll , mid , p << 1)) % mod;
 84     if(mid < r)
 85         ans = (ans + Query(l , r , mid + 1 , rr , p << 1 | 1)) % mod;
 86     update(p);
 87     return ans;
 88 }
 89 int main()
 90 {
 91     int opt , l , r , k;
 92     scanf("%d%d%lld" , &n , &m , &mod);
 93     for(int i = 1; i <= n; i++)
 94         scanf("%d" , &num[i]);
 95     Build(1 , n , 1);
 96     for(int i = 1; i <= m; i++)
 97     {
 98         scanf("%d" , &opt);    
 99         if(opt == 1)
100         {
101             scanf("%d%d%d" , &l , &r , &k);
102             Mul(l , r , 1 , n , 1 , k);
103         }
104         if(opt == 2)
105         {
106             scanf("%d%d%d" , &l , &r , &k);
107             Add(l , r , 1 , n , 1 , k);
108         }
109         if(opt == 3)
110         {
111             scanf("%d%d" , &l , &r);
112             printf("%lld\n" , Query(l , r , 1 , n , 1) % mod);
113         }
114     }
115     return 0;
116 }

 线段树

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!