Peter's codebook A blog full of codes

ZeroJudge b278 -- 說話不算話的區間求和

線段樹 + 一些持久化精神

參考 Morris 大神的文章,所以 code 可能有 87% 像 :P

(感謝 Morris 大神寫了很好的文章,他的 code 排版清楚,命名也好理解 XD)

每次操作都是建立一個新節點,因此可以回溯。

詢問時參考新舊節點的值,修改時也會參考舊節點產生新節點。

傳送門 & 參考資料

ZJ_b278

Morris 大神的文章

程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// verdict: AC
// time:    0.3s
// memory:  1.5MB
#pragma GCC target ("avx")
#pragma GCC optimize ("Os")
#include <bits/stdc++.h>
using namespace std;

struct Node {
    int lc, rc;
    long long val;
};

struct SegmentTreeP {
    enum { MAXNODE=6101010, MAXREC=500010};
    int nodeNum;
    int his[MAXREC];
    Node sg[MAXNODE];
    SegmentTreeP() : nodeNum(0) { }
    int build(int l, int r) {
        if (l>r) return 0; // illegal
        int k = nodeNum++; // allocate new node
        sg[k].lc = sg[k].rc = sg[k].val = 0;
        if (l==r) return k;
        int m = l+((r-l)>>1);
        sg[k].lc = build(l, m);
        sg[k].rc = build(m+1, r);
        return k;
    }
    void init(int N) {
        memset(his,0x00,sizeof(his[0])*MAXREC);
        memset(sg, 0x00,sizeof(sg[0])*MAXNODE);
        nodeNum = 0;
        his[0] = build(1,N);
    }
    int update(int acs, int l, int r, int q, long long val) {
        if (l>r) return 0;
        int k = nodeNum++;
        sg[k] = sg[acs];   // new node derived from acs
        if (l==r) { // modify
            sg[k].val = val;
            return k;
        }
        int m = l+((r-l)>>1);
        if (q<=m)
            sg[k].lc = update(sg[acs].lc, l, m, q, val);// update left
        else
            sg[k].rc = update(sg[acs].rc, m+1, r, q, val);// update right
        sg[k].val= sg[sg[k].lc].val + sg[sg[k].rc].val; // update
        return k;
    }
    long long query(int l, int r, int ql, int qr, int q) {
        if (l>r || l>qr || r < ql) return 0LL; // illegal
        if (l>=ql && r<=qr) { // in range
            return sg[q].val;
        }
        int m = l+((r-l)>>1);
        long long res = 0;
        if (ql<=m)
            res += query(l, m, ql, qr, sg[q].lc);
        if (m< qr)
            res += query(m+1, r, ql, qr, sg[q].rc);
        return res;
    }
};

int main(void) {
    SegmentTreeP *newTree = NULL;
    newTree = new SegmentTreeP();
    assert(newTree!=NULL);
    SegmentTreeP &tree = *newTree;
    int N, Q;
    while(scanf("%d%d", &N, &Q)==2) {
        tree.init(N);
        int preVer = 0;
        for (int i=1; i<=Q; ++i) {
            int op, l, r;
            scanf("%d%d", &op, &l);
            switch(op) {
                case 0: {
                            int rec = max(0, i-l-1);
                            tree.his[i] = tree.his[rec];
                            preVer = i;
                        }
                        break;
                case 1:
                        scanf("%d", &r);
                        tree.his[i] = tree.update(tree.his[preVer], 1,N,l,r);
                        preVer = i;
                        break;
                case 2:
                        scanf("%d", &r);
                        printf("%lld\n", tree.query(1,N,l,r,tree.his[preVer]));
                        tree.his[i] = tree.his[preVer];
                        preVer = i;
                        break;
            }
        }
    }
    delete newTree;
    return 0;
}

同場加映,用 C 寫

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// GCC: ANSI C
#pragma GCC target ("avx")
#pragma GCC optimize ("Os")
#define max(a,b) ((a)>(b)?(a):(b))
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int lc, rc;
    long long val;
} Node;

#define MAXNODE 5101010
#define MAXREC 500010
int nodeNum;
int his[MAXREC];
Node sg[MAXNODE];
int build(int l, int r) {
    if (l>r) return 0; /* illegal */
    int k = nodeNum++; /* allocate new node */
    sg[k].lc = sg[k].rc = sg[k].val = 0;
    if (l==r) return k;
    int m = l+((r-l)>>1);
    sg[k].lc = build(l, m);
    sg[k].rc = build(m+1, r);
    return k;
}
void init(int N) {
    memset(his,0x00,sizeof(his[0])*MAXREC);
    memset(sg, 0x00,sizeof(sg[0])*MAXNODE);
    nodeNum = 0;
    his[0] = build(1,N);
}
int update(int acs, int l, int r, int q, long long val) {
    if (l>r || q<l || q>r) return 0;
    int k = nodeNum++;
    sg[k] = sg[acs];   /* new node derived from acs */
    if (l==r) { /* modify */
        sg[k].val = val;
        return k;
    }
    int m = l+((r-l)>>1);
    if (q<=m)
        sg[k].lc = update(sg[acs].lc, l, m, q, val);/* update left */
    else
        sg[k].rc = update(sg[acs].rc, m+1, r, q, val);/* update right */
    sg[k].val= sg[sg[k].lc].val + sg[sg[k].rc].val; /* update */
    return k;
}
long long query(int l, int r, int ql, int qr, int q) {
    if (l>r || l>qr || r < ql) return 0LL; /* illegal */
    if (l>=ql && r<=qr) { /* in range */
        return sg[q].val;
    }
    int m = l+((r-l)>>1);
    long long res = 0;
    if (ql<=m)
        res += query(l, m, ql, qr, sg[q].lc);
    if (m< qr)
        res += query(m+1, r, ql, qr, sg[q].rc);
    return res;
}

int main(void) {
    int N, Q;
    while(scanf("%d%d", &N, &Q)==2) {
        init(N);
        int preVer = 0;
        int i=0;
        for (i=1; i<=Q; ++i) {
            int op, l, r;
            scanf("%d%d", &op, &l);
            switch(op) {
                case 0: {
                            int rec = max(0, i-l-1);
                            his[i] = his[rec];
                            preVer = i;
                        }
                        break;
                case 1:
                        scanf("%d", &r);
                        his[i] = update(his[preVer], 1,N,l,r);
                        preVer = i;
                        break;
                case 2:
                        scanf("%d", &r);
                        printf("%lld\n", query(1,N,l,r,his[preVer]));
                        his[i] = his[preVer];
                        preVer = i;
                        break;
            }
        }
    }
    return 0;
}
comments powered by Disqus