bzoj 1588营业额统计(HNOI 2002)
http://www.lydsy.com/JudgeOnline/problem.php?id=1588
splay bottom-up的数组实现。
题意就是给你一组数,求每个数与在其前面且与其最相近的数的差值的绝对值。
考虑splay二叉搜索树的特性,每新插入一个节点,比它小且最靠近它的数在是左子树中的最大值,另一半同理。
代码借鉴自: http://blog.csdn.net/ACM_cxlove?viewmode=contents
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int maxn = 1e5 + 10; 6 const int inf = 0x3f3f3f3f; 7 int pre[maxn], key[maxn], ch[maxn][2], root, size; 8 int n; 9 10 void new_node(int &r, int father, int k){ 11 r = ++size; 12 pre[r] = father; 13 key[r]= k; 14 ch[r][0] = ch[r][1] = 0; 15 } 16 17 void rotate(int x, bool d){// d = 1, right rotate 18 int y = pre[x]; 19 ch[y][!d] = ch[x][d]; 20 pre[ch[x][d]] = y; 21 if(pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; 22 //if y is not the root, link x with its grandparent 23 pre[x] = pre[y]; 24 ch[x][d] = y; 25 pre[y] = x; 26 } 27 28 void splay(int u, int dest){ 29 //root u to root dest 30 while(pre[u] != dest){ 31 if(pre[pre[u]] == dest) rotate(u, ch[pre[u]][0] == u); 32 else{ 33 int y = pre[u]; 34 int d = ch[pre[y]][0] == y; 35 if(ch[y][d] == u){//zig-zag 36 rotate(u, !d); 37 rotate(u, d); 38 }else{ 39 rotate(y, d);//zig-zig 40 rotate(u, d); 41 } 42 } 43 } 44 if(!dest) root = u; 45 } 46 47 int insert(int k){ 48 int u = root; 49 while(ch[u][key[u] < k]){ 50 if(key[u] == k) return splay(u, 0), 0; 51 u = ch[u][key[u] < k]; 52 } 53 if(key[u] == k) return splay(u, 0), 0; 54 new_node(ch[u][key[u] < k], u, k); 55 splay(ch[u][key[u] < k], 0); 56 return 1; 57 } 58 59 int get_pre(int x){ 60 int tem = ch[x][0]; 61 if(!tem) return inf; 62 while(ch[tem][1]) tem = ch[tem][1]; 63 return key[x] - key[tem]; 64 } 65 66 int get_next(int x){ 67 int tem = ch[x][1]; 68 if(tem == 0) return inf; 69 while(ch[tem][0]) tem = ch[tem][0]; 70 return key[tem] - key[x]; 71 } 72 73 int main(){ 74 //freopen("in.txt", "r", stdin); 75 while(~scanf("%d", &n)){ 76 root = size = 0; 77 int ans = 0; 78 for(int i = 1; i <= n; i++){ 79 int num; 80 if(scanf("%d", &num) == EOF) num = 0; 81 if(i == 1){ 82 ans += num; 83 new_node(root, 0, num); 84 continue; 85 } 86 if(!insert(num)) continue; 87 int a = get_next(root); 88 int b = get_pre(root); 89 ans += min(a, b); 90 } 91 printf("%d\n", ans); 92 } 93 return 0; 94 }