Peter's codebook A blog full of codes

Uva 100 -- The 3n + 1 problem

Uva 的第一題,用線段樹殺根本就是大才小用。

傳送門

Uva100

ZJ_d712 <- 這裡的測資比較硬

程式碼

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
// 在 ZeroJudge 底下測試的結果
// 3326353, AC, 96ms, 3.4MB

#include <string.h>
#define __MAX(a,b) ((a)>(b)?(a):(b))

#define MAXN 1000000
#define TREEND 3
#define TREENN MAXN*TREEND
int seg[TREENN]; 
int cl[MAXN+3];
int n3(long long int n){
    return n==1?1:(n<MAXN&&cl[n]?cl[n]:n<MAXN?cl[n]=(n&1LL?n3(3*n+1):n3(n>>1))+1:(n&1LL?n3(3*n+1):n3(n>>1))+1);
}

#define LEFT(i) ((i)<<1)
#define RIGHT(i) ((i)<<1|1)
#define IN_RANGE (qL<=L && qR>=R)
#define OO_RANGE (L>qR || R<qL)

void build(int L, int R, int lev) {
    if (L==R) {
        seg[lev] = n3(L);
        return;
    }
    int M = (L+R)>>1;
    if (L<=M)
        build(L, M, LEFT(lev));
    if (M <R)
        build(M+1, R, RIGHT(lev));
    seg[lev] = __MAX(seg[LEFT(lev)] , seg[RIGHT(lev)]);
}

int query(int L, int R, int qL, int qR, int flag) {
    if (IN_RANGE) return seg[flag];
    int M=(L+R)>>1;
    int left=0, right=0;
    if (qL<=M)
        left = query(L,M,qL,qR,LEFT(flag));
    if (M <qR) 
        right = query(M+1,R,qL,qR,RIGHT(flag));
    return __MAX(left,right); 
}

void init() {
    memset(cl, 0x00, sizeof(cl[0])*MAXN);
    memset(seg,0x00, sizeof(seg[0])*TREENN);
    build(1, MAXN, 1);
}
#undef IN_RANGE
#undef OO_RANGE
#undef LEFT
#undef RIGHT

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    init();
    int l, r;
    while(scanf("%d%d",&l,&r)==2) {
        int tl=l, tr=r;
        if(tl>tr) tl^=tr^=tl^=tr;
        printf("%d %d %d\n", l, r, query(1, MAXN, tl, tr, 1));
    }
    return 0;
}
comments powered by Disqus