Uva 的第一題,用線段樹殺根本就是大才小用。
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;
}