Peter's codebook A blog full of codes

POJ 3468 -- A Simple Problem with Integers

線段樹

A simple problem? 當真?

(雖然是個模板題…)

解法

就是線段樹模板題,需要建出一棵支援區間修改、區間查詢的線段樹。

使用懶標記實現。

本題測資範圍較大,必須開 long long int。

還有使用 cin, cout 時,

請配合

    ios::sync_with_stdio(false);
    cin.tie(0);

使用,以免 TLE

傳送門

POJ3468

程式碼

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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char buff[50000000];
long long int seg[500100];
long long int lazy[500100];

void init() {
    memset(buff,0x00,sizeof(buff));
    memset(seg,0x00,sizeof(seg));
    memset(lazy,0x00,sizeof(lazy));
}

void push(int idx, int L, int M, int R) {
    if(lazy[idx]==0LL) return;
    // 壓懶標記
    lazy[idx<<1] += lazy[idx];
    lazy[idx<<1|1] += lazy[idx];
    seg[idx<<1] += lazy[idx]*(long long int)(M-L+1);
    seg[idx<<1|1] += lazy[idx]*(long long int)(R-M);
    lazy[idx] = 0LL; // reset lz tag
}

void pull(int idx, int L, int M, int R) {
    seg[idx] = seg[idx<<1|1]+seg[idx<<1];
}

void update(int L, int R, int qL, int qR, int idx, long long int val) {
    if (L>qR || R<qL) return;
    if (L>=qL && R<=qR) {
        seg[idx]+=(val*(R-L+1));
        lazy[idx]+=val;
        return; // 放懶標
    }
    int M = L+((R-L)>>1);
    push(idx, L, M, R);
    update(L, M, qL, qR, idx<<1, val);
    update(M+1, R, qL, qR, idx<<1|1, val);
    pull(idx, L, M, R);
}

long long query(int L, int R, int qL, int qR, int idx) {
    if (L>qR || R<qL) return 0LL;
    if (L>=qL && R<=qR) return seg[idx];
    int M = L+((R-L)>>1);
    push(idx, L, M, R);
    long long l=0, r=0;
    l = query(L,M,qL,qR,idx<<1);
    r = query(M+1,R,qL,qR,idx<<1|1);
    pull(idx, L, M, R);
    return l+r;
}

#define RL() fgets(buff, sizeof(buff)-100, stdin)
int main(void) {
    int N, Q, i;
    char *readPtr=NULL;
    RL();
    sscanf(buff, "%d%d", &N, &Q);
    RL();
    i=1;
    readPtr = strtok(buff, " \n");
    while(readPtr) {
        long long int input=0;
        sscanf(readPtr, "%lld", &input);
        update(1, N, i, i, 1, input);
        readPtr = strtok(NULL, " \n");
        ++i;
    }
    while(Q--) {
        char op;
        int l, r;
        long long int x;
        RL();
        int cnt = sscanf(buff, "%1c %d %d %lld", &op, &l, &r, &x);
        if (cnt==4) { //update
            update(1, N, l, r, 1, x);
        } else {
            printf("%lld\n", query(1,N,l,r,1));
        }
    }

    return 0;
}

類題 ZeroJudge d799

ZJd799 傳送門

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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

long long int seg[1500100];
long long int lazy[1500100];

#define push(idx, L, M, R) \
    if(lazy[idx]!=0LL) { \
        lazy[idx<<1] += lazy[idx]; \
        lazy[idx<<1|1] += lazy[idx]; \
        seg[idx<<1] += lazy[idx]*(long long int)(M-L+1); \
        seg[idx<<1|1] += lazy[idx]*(long long int)(R-M); \
        lazy[idx] = 0LL; } 


#define pull(idx) \
{ seg[idx] = seg[idx<<1|1]+seg[idx<<1]; }

void update(int L, int R, int qL, int qR, int idx, long long int val) {
    if (L>qR || R<qL) return;
    if (L>=qL && R<=qR) {
        seg[idx]+=(val*(R-L+1));
        lazy[idx]+=val;
        return; // 放懶標
    }
    int M = L+((R-L)>>1);

    push(idx, L, M, R);

    update(L, M, qL, qR, idx<<1, val);
    update(M+1, R, qL, qR, idx<<1|1, val);

    pull(idx);
}

long long query(int L, int R, int qL, int qR, int idx) {
    if (L>qR || R<qL) return 0LL;
    if (L>=qL && R<=qR) return seg[idx];
    int M = L+((R-L)>>1);

    push(idx, L, M, R);

    long long l=0, r=0;
    l = query(L,M,qL,qR,idx<<1);
    r = query(M+1,R,qL,qR,idx<<1|1);

    pull(idx);

    return l+r;
}
#undef push
#undef pull

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