BZOJ1588 [HNOI2002]营业额统计

BZOJ1588

splay。

把每天的营业额加入splay,查找前驱和后继,统计即可。

注意使用双旋的splay,因为单旋在链状树的情况下时间复杂度会退化。具体证明去问Tarjan。

也可使用其他平衡树或双向链表。双向链表的做法可参考 朱晨光《基本数据结构在信息学竞赛中的应用》。


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
103
104
105
106
107
108
109
110
111
112
#include <cstdio>
#include <algorithm>
#include <cctype>


const int N = 32767 + 10, INF = 0x3F3F3F3F;


int fat[N], son[N][2], val[N], root, tot;


void insert(int );
void splay(int );
void rotate(int );
int pre(void);
int suc(void);
int read(void);


int main(void)
{
    int ans;
    for (int n = read(); n--; )
    {
        int x = read();
        if (root)
        {
            insert(x);
            ans += std::min(x - pre(), suc() - x);
        }
        else
        {
            root = tot = 1;
            val[root] = x;
            ans = x;
            insert(INF);
            insert(-INF);
        }
    }
   
    printf("%d\n", ans);
   
    return 0;
}


void insert(int v)
{
    int x = root;
    for (; son[x][v > val[x]]; x = son[x][v > val[x]])
        ;
    val[++tot] = v;
    fat[tot] = x;
    son[x][v > val[x]] = tot;
    splay(tot);
}


void splay(int x)
{
    for (int y; (y = fat[x]) > 0; )
    {
        if (fat[y])
            rotate((son[y][0] == x) ^ (son[fat[y]][0] == y) ? y : x);
        rotate(x);
    }
    root = x;
}


void rotate(int x)
{
    int y = fat[x], s = (x == son[y][1]);
    fat[son[x][s ^ 1]] = y;
    son[y][s] = son[x][s ^ 1];
    if (fat[y])
        son[fat[y]][y == son[fat[y]][1]] = x;
    fat[x] = fat[y];
    son[x][s ^ 1] = y;
    fat[y] = x;
}


int pre(void)
{
    for (int x = son[root][0]; ; x = son[x][1])
        if (!son[x][1])
            return val[x];
    return val[root];
}


int suc(void)
{
    for (int x = son[root][1]; ; x = son[x][0])
        if (!son[x][0])
            return val[x];
    return val[root];
}


inline int read(void)
{
    char x;
    while (x = getchar(), x != '-' && !isdigit(x))
        ;
    bool flag = (x == '-');
    int num = (flag ? getchar() : x) - '0';
    while (isdigit(x = getchar()))
        (num *= 10) += x - '0';
    return flag ? -num : num;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注