线段树日记

因为记笔记是很不好玩的事情……

 

https://www.luogu.org/recordnew/show/18875922

我写的第一颗线段树,支持单点修改、查询区间和,常数很大。

——2019.5.8晚

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 struct Node{
 5     int l , r;
 6     int val;
 7 }t[500001 << 3];
 8 int a[500001], n, m;
 9 void build(int ind, int l, int r) {
10     if(l == r) {
11         t[ind].l = l;
12         t[ind].r = r;
13         t[ind].val = a[l];
14         return;
15     }
16     t[ind].l = l;
17     t[ind].r = r;
18     int mid = (l + r) >> 1;
19     build(ind << 1, l, mid);
20     build((ind << 1) + 1, mid + 1, r);
21     t[ind].val = t[ind << 1].val + t[(ind << 1) + 1].val;
22     return;
23 }
24 
25 //void search(int ind) {
26 //    cout << t[ind].l << "<->" << t[ind].r << '\n'; 
27 //    if(t[ind << 1].val) search(ind << 1);
28 //    if(t[(ind << 1) + 1].val) search((ind << 1) + 1);
29 //}
30 //第一次写, 很好奇地先序遍历了一下 
31 
32 void updata(int x, int val, int ind) {
33     //cout << t[ind].l << '-' << t[ind].r << '\n';
34     if(t[ind].l == t[ind].r) {
35         t[ind].val += val;
36         return;
37     }
38     int mid = (t[ind].l + t[ind].r) / 2;
39     if(x > mid) {
40         updata(x, val, (ind << 1) + 1);
41     }
42     else {
43         updata(x, val, ind << 1);
44     }
45     t[ind].val += val;
46 }
47 
48 int ask(int x, int y, int ind) {
49     if(t[ind].l == t[ind].r) return t[ind].val;
50     int mid = (t[ind].l + t[ind].r) >> 1;
51     if(x <= mid && y > mid) return ask(x , mid, ind << 1) + ask(mid + 1, y, (ind << 1) + 1);
52     else if(x <= mid && y <= mid) {
53         return ask(x, y, ind << 1);
54     }
55     else return ask(x, y, (ind << 1) + 1);
56 }
57 
58 int main() {
59     cin >> n >> m;
60     for(register int i = 1; i <= n; ++i) {
61         scanf("%d", &a[i]);
62     }
63     build(1, 1, n);
64 //    search(1);
65     int oper = 0, x = 0, y = 0, k = 0;
66     for(int i = 1; i <= m; ++i) {
67         scanf("%d", &oper);
68         switch(oper) {
69             case 1:
70                 scanf("%d%d", &x, &k);
71                 updata(x,k,1);
72                 break;
73             case 2:
74                 scanf("%d%d", &x, &y);
75                 cout << ask(x,y,1) << '\n';
76                 break;
77         }
78     }
79     return 0;
80 }

 

https://www.luogu.org/recordnew/show/18880248

 第二颗线段树!支持区间加和、单点查询数值,这次没有超时。

——2019.5.9上午

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cctype>
 4 //对于100%的数据:N<=500000,M<=500000 区间加,单点查询 
 5 using namespace std;
 6 int read() {
 7     char c = getchar();
 8     int x = 0, f = 1;
 9     while(!isdigit(c)) {
10         if(c == '-') f = -1;
11         c = getchar();
12     }
13     while(isdigit(c)) {
14         x = x*10 + c - '0';
15         c = getchar();
16     }
17     return x * f;
18 }
19 struct Node{
20     int l, r;
21     int val, tag;
22 }t[500000 << 1 + 1];
23 int n, m, a[500001];
24 
25 void build(int ind, int left, int right) {
26     if(left == right) {
27         t[ind].l = left;
28         t[ind].r = right;
29         t[ind].val = a[left];
30         return;
31     }
32     int mid = (left + right) >> 1;
33     t[ind].l = left;
34     t[ind].r = right;
35     build(ind << 1, left, mid);
36     build((ind<<1) + 1, mid + 1, right);
37     t[ind].val = t[ind << 1].val + t[(ind<<1) + 1].val;
38     return;
39 }
40 
41 void updata(int left, int right, int value, int ind) {
42     if(left == t[ind].l && right == t[ind].r) {
43         t[ind].tag += value;
44         return;
45     }
46     int mid = (t[ind].l + t[ind].r) >> 1;
47     if(left > mid) updata(left, right, value, (ind << 1) + 1);
48     else
49     if(right < mid+1) updata(left, right, value, ind << 1);
50     else {
51         updata(left, mid, value, ind << 1);
52         updata(mid + 1, right, value, (ind << 1) + 1);
53     }
54     return;
55 }
56 
57 int ask(int x, int ind) {
58     if(t[ind].l == t[ind].r) {
59         t[ind].val += t[ind].tag;
60         t[ind].tag = 0;
61         return t[ind].val;
62     }
63     t[ind << 1].tag += t[ind].tag;
64     t[(ind << 1) + 1].tag += t[ind].tag;
65     t[ind].val += t[ind].tag;
66     t[ind].tag = 0;
67     int mid = (t[ind].l + t[ind].r) >> 1;
68     if(x > mid) return ask(x, (ind << 1) + 1);
69     else return ask(x, ind << 1);
70 }
71 
72 int main() {
73     n = read();
74     m = read();
75     for(int i = 1; i <= n; ++i) {
76         a[i] = read();
77     }
78     build(1,1,n);
79     int oper, x, y, k;
80     for(int i = 1; i <= m; ++i) {
81         oper = read();
82         switch(oper) {
83             case 1:
84                 x = read(), y = read(), k = read();
85                 updata(x, y, k, 1); break;
86             case 2:
87                 x = read();
88                 cout << ask(x,1) << '\n';
89                 break;
90         }
91     }
92     return 0;
93 }

 

第三颗,支持区间加和,查询区间和,就是卡不过常数去

https://loj.ac/submission/445888

——2019.5.9晚

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 struct Node{
 5     long long l, r;
 6     long long val, tag;
 7 }t[1000000 << 2 + 1];
 8 long long a[1000001], n, m, oper, x, y, k;
 9 
10 long long read() {
11     long long x = 0, f = 1;
12     char c = getchar();
13     while(c < '0' || c > '9') {
14         if(c == '-') f = -f;
15         c = getchar();
16     }
17     while(c >= '0' && c <= '9') {
18         x = x*10 + c - '0';
19         c = getchar();
20     }
21     return x * f;
22 }
23 void build(long long ind, long long left, long long right) {
24     t[ind].l = left, t[ind].r = right;
25     if(left == right) {
26         t[ind].val = a[left];
27         return;
28     }
29     long long mid = (left + right) >> 1;
30     build(ind << 1, left, mid);
31     build((ind << 1) + 1, mid + 1, right);
32     t[ind].val = t[ind << 1].val + t[(ind << 1) + 1].val;
33     return;
34 }
35 
36 void updata(long long ind, long long left, long long right, long long value) {
37     if(left == t[ind].l && right == t[ind].r) {
38         t[ind].tag += value;
39         return;
40     }
41     t[ind].val += (right - left + 1) * value;
42     long long mid = (t[ind].l + t[ind].r) >> 1;
43     if(left > mid) {
44         updata((ind << 1) + 1, left, right, value);
45     }
46     else if(mid >= right) {
47         updata(ind << 1, left, right, value);
48     }
49     else {
50         updata(ind << 1, left, mid, value);
51         updata((ind << 1) + 1, mid + 1, right, value);
52     }
53 }
54 
55 long long ask(long long ind, long long left, long long right) {
56     t[ind].val += (t[ind].r - t[ind].l + 1) * t[ind].tag;
57     t[ind << 1].tag += t[ind].tag;
58     t[(ind << 1) + 1].tag += t[ind].tag;
59     t[ind].tag = 0;
60     if(t[ind].l == left && t[ind].r == right) {
61         return t[ind].val;
62     }  
63     long long mid = (t[ind].l + t[ind].r) >> 1;
64     if(left > mid) {
65         return ask((ind << 1) + 1, left, right);
66     }
67     else if(mid >= right) {
68         return ask(ind << 1, left, right);
69     }
70     else {
71         return ask(ind << 1, left, mid) + ask((ind << 1) + 1, mid + 1, right);
72     }
73 }
74 int main() {
75     n = read(), m = read();
76     for(long long i = 1; i <= n; ++i)
77         a[i] = read();
78     
79     build(1, 1, n);
80     
81     for(long long i = 1; i <= m; ++i) {
82         oper = read();
83         switch(oper) {
84             case 1:
85                 x = read(), y = read(), k = read();
86                 updata(1, x, y, k); break;
87             case 2:
88                 x = read(), y = read();
89                 cout << ask(1, x, y) << '\n';
90                 break;
91         }
92     }
93     return 0;
94 }

 

 今天早上痛定思痛,换一种线段树的写法,做第一颗树栽了的那题

快了不少,这就是第四颗了。

https://www.luogu.org/recordnew/show/18905672             ——5.10 / 2019

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 int t[500000 << 2 + 1], n, m, a[500001], oper, x, y, k;
 5 int read() {
 6     char c = getchar();
 7     int x = 0, f = 1;
 8     while(c < '0' || c > '9') {
 9         if(c == '-') f = -1;
10         c = getchar();
11     }
12     while(c >= '0' && c <= '9') {
13         x = x*10 + c - '0';
14         c = getchar();
15     }
16     return x*f;
17 }
18 
19 void build(int ind, int l, int r) {
20     if(l == r) {
21         t[ind] = a[l];
22         return;
23     }
24     int m = (l + r) >> 1;
25     build(ind << 1, l, m);
26     build((ind<<1) + 1, m + 1, r);
27     t[ind] = t[ind << 1] + t[(ind<<1) + 1];
28 }
29 
30 void updata(int ind, int l, int r, int x, int val) {
31     t[ind] += val;
32     if(l == r) return;
33     int m = (l + r) >> 1;
34     if(x > m) updata((ind<<1) + 1, m + 1, r, x, val);
35     else if(x <= m) updata(ind << 1, l, m, x, val);
36 }
37 
38 int ask(int l, int r, int s, int e, int ind) {
39     if(l == s && r == e) return t[ind];
40     int m = (s + e) >> 1;
41     if(l > m) return ask(l, r, m+1, e, (ind<<1) + 1);
42     else if(r <= m) return ask(l, r, s, m, ind << 1);
43     else return ask(l, m, s, m, ind << 1) + ask(m+1, r, m+1, e, (ind<<1) + 1);
44 }
45 
46 int main() {
47     n = read(), m = read();
48     for(int i = 1; i <= n; ++i)
49         a[i] = read();
50     build(1, 1, n);
51     for(int i = 1; i <= m; ++i) {
52         oper = read();
53         switch(oper) {
54             case 1:
55                 x = read(), k = read();
56                 updata(1, 1, n, x, k); break;
57             case 2:
58                 x = read(), y = read();
59                 cout << ask(x, y, 1, n, 1) << '\n'; break;
60         }
61     }
62     return 0;
63 }

 

 2019,5,12:第五颗

通过对线段树的思考明白了冗余信息的计算对速度的拖延。

以下一块代码是第五颗,有优化的余地。

  1 #include<cstdio>
  2 #include<iostream>
  3 using namespace std;
  4 struct Node{
  5     long long l, r, mid;
  6     long long val, tag;
  7 }t[100000 << 3];
  8 long long n, m, a[100001];
  9 long long read() {
 10     char c = getchar();
 11     long long x = 0, f = 1;
 12     while(c < '0' || c > '9') {
 13         if(c == '-') f = -1;
 14         c = getchar();
 15     }
 16     while(c >= '0' && c <= '9') {
 17         x = x * 10 + c - '0';
 18         c = getchar();
 19     }
 20     return x * f;
 21 }
 22 
 23 inline long long lc(long long k) {
 24     return k << 1;
 25 }
 26 inline long long rc(long long k) {
 27     return k << 1 | 1;
 28 }
 29 
 30 inline void pushdown(long long ind) {
 31     t[lc(ind)].tag += t[ind].tag;
 32     t[rc(ind)].tag += t[ind].tag;
 33 
 34     t[lc(ind)].val += t[ind].tag * (t[lc(ind)].r - t[lc(ind)].l + 1);
 35     t[rc(ind)].val += t[ind].tag * (t[rc(ind)].r - t[rc(ind)].l + 1);
 36     t[ind].tag = 0;
 37 }
 38 
 39 inline void pushup(long long ind) {
 40     t[ind].val = t[lc(ind)].val + t[rc(ind)].val;
 41 }
 42 
 43 
 44 
 45 void build(long long i, long long x, long long y) {
 46     t[i].l = x, t[i].r = y;
 47     t[i].mid = (x + y) >> 1;
 48     if(x == y) {
 49         t[i].val = a[x];
 50         return;
 51     }
 52     build(lc(i), x, t[i].mid);
 53     build(rc(i), t[i].mid + 1, y);
 54     pushup(i);
 55 }
 56 
 57 void updata(long long ind, long long x, long long y, long long k) {
 58     if(t[ind].tag) pushdown(ind);
 59     
 60     if(t[ind].l == x && t[ind].r == y) {
 61         t[ind].val += (y - x + 1) * k;
 62         t[ind].tag += k;
 63         return;
 64     }
 65     
 66     if(y <= t[ind].mid) updata(lc(ind), x, y, k);
 67     else
 68     if(x > t[ind].mid) updata(rc(ind), x, y, k);
 69     else {
 70         updata(lc(ind), x, t[ind].mid, k);
 71         updata(rc(ind), t[ind].mid + 1, y, k);
 72     }
 73     
 74     pushup(ind);
 75 }
 76 
 77 long long ask(long long ind, long long x, long long y) {
 78     if(t[ind].tag) pushdown(ind);
 79     
 80     if(t[ind].l == x && t[ind].r == y) return t[ind].val;
 81     
 82     if(y <= t[ind].mid) return ask(lc(ind), x, y);
 83     else
 84     if(x > t[ind].mid) return ask(rc(ind), x, y);
 85     else {
 86         return ask(lc(ind), x, t[ind].mid) + ask(rc(ind), t[ind].mid + 1, y);
 87     }
 88 }
 89 
 90 int main() {
 91     n = read(), m = read();
 92     for(long long i = 1; i <= n; ++i)
 93         a[i] = read();
 94     build(1, 1, n);
 95     long long opt, x, y, k;
 96     for(long long i = 1; i <= m; ++i) {
 97         opt = read();
 98         if(opt == 1) {
 99             x = read(), y = read(), k = read();
100             updata(1, x, y, k);
101         }
102         else {
103             x = read(), y = read();
104             cout << ask(1, x, y) << '\n';
105         }
106     }
107     return 0;
108 }

 

 2019.5.17  第n颗, 速度好快啊, define真方便啊。(忽然发现第三颗更快~qwq)

https://www.luogu.org/recordnew/show/19106653

 

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 #define ls (ind << 1)
 5 #define rs ((ind << 1) + 1)
 6 #define mid ((l + r) >> 1)
 7 long long a[100001], v[100000 << 2], tag[100000 << 2], k;
 8 
 9 inline void pushdown(long long ind, long long l, long long r) {
10     if(l == r) {
11         tag[ind] = 0;
12         return;
13     }
14     
15     tag[ls] += tag[ind];
16     tag[rs] += tag[ind];
17 
18     v[ls] += (mid - l + 1) * tag[ind];
19     v[rs] += (r - mid) * tag[ind];
20 
21     tag[ind] = 0;
22 }
23 
24 void build(long long ind, long long l, long long r) {
25     if(l == r) {
26         v[ind] = a[l];
27         return;
28     }
29     build(ls, l, mid);
30     build(rs, mid + 1, r);
31     v[ind] = v[ls] + v[rs];
32 }
33 
34 void add(long long ind, long long l, long long r, long long x, long long y) {
35     
36     if(tag[ind])
37     pushdown(ind, l, r);
38     
39     if(l == x && r == y) {
40         v[ind] += (r - l + 1) * k;
41         tag[ind] += k;
42         return;
43     }
44     
45     if(y <= mid) add(ls, l, mid, x, y);
46     else if(x > mid) add(rs, mid + 1, r, x, y);
47          else {
48              add(ls, l, mid, x, mid);
49                add(rs, mid + 1, r, mid + 1, y);
50          }
51     
52     v[ind] = v[ls] + v[rs];
53 }
54 
55 long long ask(long long ind, long long l, long long r, long long x, long long y) {
56     
57     
58     if(l == x && r == y) {
59         return v[ind];
60     }
61     
62     if(tag[ind])
63     pushdown(ind, l, r);
64     
65     if(y <= mid) return ask(ls, l, mid, x, y);
66     else if(x > mid) return ask(rs, mid + 1, r, x, y);
67          else return ask(ls, l, mid, x, mid) + ask(rs, mid + 1, r, mid + 1, y);
68 }
69 
70 int main() {
71     long long n, m;
72     scanf("%lld%lld", &n, &m);
73     for(long long i = 1; i <= n; ++i)
74         scanf("%lld", &a[i]);
75     build(1, 1, n);
76     long long opt, x, y;
77     for(long long i = 1; i <= m; ++i) {
78         scanf("%lld", &opt);
79         if(opt == 2) {
80             scanf("%lld%lld", &x, &y);
81             cout << ask(1, 1, n, x, y) << '\n';
82         }
83         else {
84             scanf("%lld%lld%lld", &x, &y, &k);
85             add(1, 1, n, x, y);
86         }
87     }
88     return 0;
89 }

 

 2019.5.21

第n+1颗?学会了用指针写线段树。

https://www.luogu.org/recordnew/show/19239222

但是结果很不好

#include<cstdio>
#include<iostream>

using namespace std;
#define mid (l+r >> 1)
const int maxn = 100000;

struct Node{
    long long val, tag;
    Node *lc, *rc;
};

Node* root;
long long k;

inline void pushdown(Node* &u, int l, int r) {
    if(l == r) {
        u->tag = 0;
        return;
    }
    
    u->lc->val += (mid-l+1) * u->tag;
    u->rc->val += (r-mid) * u->tag;
    
    u->lc->tag += u->tag;
    u->rc->tag += u->tag;
    
    u->tag = 0;
}

void build(Node* &u, int l, int r) {
    u = new Node;

    if(l == r) {
        scanf("%lld", &u->val);
        return;
    }
    
    build(u->lc, l, mid);
    build(u->rc, mid+1, r);
    
    u->val = u->lc->val + u->rc->val;
}

void add(Node* &u, int x, int y, int l, int r) {
    if(x == l && y == r) {
        u->val += (r-l+1)*k;
        u->tag += k;
        return;
    }
    
    if(y <= mid) add(u->lc, x, y, l, mid);
    else
    if(x > mid) add(u->rc, x, y, mid+1, r);
    else {
        add(u->lc, x, mid, l, mid);
        add(u->rc, mid+1, y, mid+1, r);
    }
    
    u->val = u->lc->val + u->rc->val;
}

long long query(Node* &u, int x, int y, int l, int r) {
    if(u->tag) pushdown(u, l, r);
    
    if(l == r) return u->val;
    
    if(y <= mid) return query(u->lc, x, y, l, mid);
    if(x > mid) return query(u->rc, x, y, mid+1, r);
    
    return query(u->lc, x, mid, l, mid) + query(u->rc, mid+1, y, mid+1, r);
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);

    build(root, 1, n);
    
    int opt, x, y;
    
    for(int i = 1; i <= m; ++i) {
        scanf("%d", &opt);
        if(opt == 1) {
            scanf("%d%d%lld", &x, &y, &k);
            add(root, x, y, 1, n);
        }
        else {
            scanf("%d%d", &x, &y);
            cout << query(root, x, y, 1, n) <<'\n';
        }
    }
    
    return 0;
}

 

2019.5.21晚21:46:07

依旧是指针线段树,但是好了太多。

https://www.luogu.org/recordnew/show/19254090

 

#include<cstdio>
#include<iostream>
using namespace std;
struct Node{
    int l, r;
    long long val, tag;
    Node *lc, *rc;
    
    Node(int x, int y, long long v, long long t, Node* a, Node* b) {
        l = x;
        r = y;
        val = v;
        tag = t;
        lc = a;
        rc = b;
    }
};

Node* root;

int opt, x, y;
long long k, a[100001];

Node* build(int l, int r) {

    if(l == r) return new Node(l, r, a[l], 0, NULL, NULL);
    
    int mid = (l + r) >> 1;
    
    Node *left = build(l, mid), *right = build(mid+1, r);
    
    return new Node(l, r, left->val + right->val, 0, left, right);
    
}

inline void pushdown(Node* &u) {
    if(u->l == u->r) {
        u->tag = 0;
        return;
    }
    
    int mid = (u->r + u->l) >> 1;
    
    u->lc->val += (mid - u->l + 1) * u->tag;
    u->rc->val += (u->r - mid) * u->tag;
    
    u->lc->tag += u->tag;
    u->rc->tag += u->tag;
    
    u->tag = 0;
}

void modify(int l, int r, Node* &u) {
    if(u->tag) pushdown(u);
    
    if(l == u->l && r == u->r) {
        u->val += (r - l + 1) * k;
        u->tag += k;
        return;
    }
    
    int mid = (u->l + u->r) >> 1;
    
    if(r < mid+1) modify(l, r, u->lc);
    else if(l > mid) modify(l, r, u->rc);
         else {
         	modify(l, mid, u->lc);
         	modify(mid+1, r, u->rc);
         }
    
    u->val = u->lc->val + u->rc->val;
}



long long query(int l, int r, Node* &u) {
    
    if(u->tag) pushdown(u);
    
    if(l == u->l && r == u->r) return u->val;
    
    int mid = (u->l + u->r) >> 1;
    
    if(r < mid+1) return query(l, r, u->lc);
    if(l > mid) return query(l, r, u->rc);
    
    return query(l, mid, u->lc) + query(mid+1, r, u->rc);
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    
    for(register int i = 1; i <= n; ++i)
        scanf("%lld", &a[i]);

    root = build(1, n);

    for(register int i = 1; i <= m; ++i) {
        scanf("%d", &opt);
        if(opt == 1) {
            scanf("%d%d%lld", &x, &y, &k);
            modify(x, y, root);
        }
        else {
            scanf("%d%d", &x, &y);
            printf("%lld\n", query(x, y, root));
        }
    }
    
    return 0;
}

 

2019.5.22

第n+3颗,入门了?(笑

https://www.luogu.org/recordnew/show/19259419

// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
using namespace std;

struct Node{
    long long val, tag1, tag2;
    long long begin, end;
    Node *ls, *rs;
    
    Node(long long v, long long b, long long e, Node* l, Node* r) {
        val = v, begin = b, end = e, ls = l, rs = r;
        tag1 = 0, tag2 = 1;
    }
}*root; 


long long a[100001], n, m, MOD;

long long k, opt, x, y;

void read(long long &x) {
    x = 0;
    long long f = 1;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = x*10 + c - '0';
        c = getchar();
    }
    x *= f;
}

inline void Pushdown(Node* &u) {
    if(u->tag1 == 0 && u->tag2 == 1) return;
    
    if(u->begin == u->end) {
        u->tag1 = 0;
        u->tag2 = 1;
        return;
    }
    
    long long k1 = u->tag1%MOD, k2 = u->tag2%MOD;
    
    long long l = u->begin, r = u->end;
    long long mid = (l+r)>>1;
    
    u->tag1 = 0, u->tag2 = 1;
    
    u->ls->tag1 = (u->ls->tag1 * k2) % MOD;
    u->rs->tag1 = (u->rs->tag1 * k2) % MOD;
    u->ls->tag1 = (u->ls->tag1 + k1) % MOD;
    u->rs->tag1 = (u->rs->tag1 + k1) % MOD;
    
    u->ls->tag2 = (u->ls->tag2 * k2) % MOD;
    u->rs->tag2 = (u->rs->tag2 * k2) % MOD;
    
    u->ls->val = (u->ls->val * k2) % MOD;
    u->ls->val = (u->ls->val + k1*(mid-l+1)%MOD ) % MOD;
    
    u->rs->val = (u->rs->val * k2) % MOD;
    u->rs->val = (u->rs->val + k1*(r-mid)%MOD ) % MOD;
    
}

Node* build(long long l, long long r) {
    if(l == r) return new Node(a[l], l, r, NULL, NULL);
    long long mid = (l+r)>>1;
    Node *left = build(l, mid), *right = build(mid+1, r);
    return new Node((left->val + right->val) % MOD, l, r, left, right);
}

void Mul_modify(Node* &u, long long l, long long r) {
    
    if(l == u->begin && r == u->end) {
        u->val = (u->val % MOD * k % MOD) % MOD;
        
        u->tag1 = (u->tag1 % MOD * k % MOD) % MOD;
        u->tag2 = (u->tag2 % MOD * k % MOD) % MOD;
        return;
    }
    Pushdown(u);
    long long mid = (u->begin + u->end) >> 1;
    
    if(r < mid+1) Mul_modify(u->ls, l, r);
    else if(l > mid) Mul_modify(u->rs, l, r);
         else {
         	Mul_modify(u->ls, l, mid);
         	Mul_modify(u->rs, mid+1, r);
         }
    
    u->val = (u->ls->val % MOD + u->rs->val % MOD) % MOD + MOD;
}

void Add_modify(Node* &u, long long l, long long r) {
    
    if(l == u->begin && r == u->end) {
        
        u->val = (u->val % MOD + (u->end - u->begin + 1) * k % MOD) % MOD;
        u->tag1 = (u->tag1 % MOD + k % MOD) % MOD;
        return;
    }
    Pushdown(u);
    long long mid = (u->begin + u->end) >> 1;
    
    if(r < mid+1) Add_modify(u->ls, l, r);
    else if(l > mid) Add_modify(u->rs, l, r);
         else {
         	Add_modify(u->ls, l, mid);
         	Add_modify(u->rs, mid+1, r);
         }
         
    u->val = (u->ls->val % MOD + u->rs->val % MOD) % MOD;
}

long long query(Node* &u, long long l, long long r) {
    
    
    if(l == u->begin && r == u->end) return u->val%MOD;
    Pushdown(u);
    long long mid = (u->begin + u->end) >> 1;
    
    if(r < mid+1) return query(u->ls, l, r)%MOD;
    if(l > mid) return query(u->rs, l, r)%MOD;
    
    return query(u->ls, l, mid)%MOD + query(u->rs, mid+1, r)%MOD;
}

int main() {
    read(n), read(m), read(MOD);
    
    for(register long long i = 1; i <= n; ++i)
        read(a[i]), a[i] %= MOD;
        
    root = build(1, n);
    
    for(register long long i = 1; i <= m; ++i) {
        read(opt);
        switch(opt) {
            case 1:
                read(x), read(y), read(k);
                Mul_modify(root, x, y); break;
            case 2:
                read(x), read(y), read(k);
                Add_modify(root, x, y); break;
            case 3:
                read(x), read(y);
                cout << (query(root, x, y) % MOD + MOD) % MOD<<'\n';
        }
    }
    return 0;
}

  

转载于:https://www.cnblogs.com/tztqwq/p/10836368.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值