zoukankan      html  css  js  c++  java
  • TYVJ1185 营业额统计 Splay

    该题应该有很多的解法,想过用二分查找,但是排序操作的复杂度让我们伤不起。这里用Splay来实现是很方便的。首先插入一个点,即第一个点,然后再依次用二叉排序树方式插入当前点,再把该点旋转到根部(这样方便我们找前驱和后继,否则需要中序遍历整棵树来确定),再在存在前驱和后继的情况下寻找前驱和后继。接下来就很好办了。

    代码如下:

    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define L(x) tree[x].ch[0]
    #define R(x) tree[x].ch[1]
    #define INF 0x3ffffff
    #define MAXN 33000
    using namespace std;
    
    int N, seq[MAXN], que[MAXN], front, rt;
    
    struct Node
    {
        int v, ch[2], fa;
        void New(int v, int fa) {
            this->v = v, this->fa = fa;
            ch[0] = ch[1] = 0;
        }
    }tree[MAXN];
    
    void init()
    {
        for (int i = 0; i < MAXN; ++i) {
            que[i] = i;
        }
        rt = que[++front];
        tree[rt].New(seq[1], 0);
    }
    
    int insert(int &rt, int &num, int fa) // 引用仅仅为了速度考虑
    {
        if (rt == 0) {
            // 说明这个节点是待填充的
            int x = que[++front];
            rt = x;
            tree[x].New(num, fa);
            return x;
        }
        if (num > tree[rt].v) { 
            return insert(R(rt), num, rt); 
        }
        else {
            return insert(L(rt), num, rt);
        }
    }
    
    void rotate(int x, int f)
    {
        int y = tree[x].fa, z = tree[y].fa;
        tree[y].ch[!f] = tree[x].ch[f];
        tree[ tree[y].ch[!f] ].fa = y;
        tree[x].ch[f] = y;
        tree[y].fa = x;
        tree[x].fa = z;
        if (z) {
            tree[z].ch[ R(z) == y ] = x;
        }
    }
    
    void splay(int x, int obj)
    {
        int y, z;
        while (tree[x].fa != obj) {
            y = tree[x].fa, z = tree[y].fa;
            if (z == obj) {
                rotate(x, L(y) == x);
            }
            else if (x == L(y) && y == L(z)) {
                rotate(y, 1), rotate(x, 1);
            }
            else if (x == R(y) && y == R(z)) {
                rotate(y, 0), rotate(x, 0);
            }
            else if (x == R(y) && y == L(z)) {
                rotate(x, 0), rotate(x, 1);
            }
            else {
                rotate(x, 1), rotate(x, 0);
            }
        }
        if (obj == 0) {
            rt = x;
        }
    }
    
    int findPre(int rt, int num)
    {
        if (R(rt) == 0) {
            return tree[rt].v;
        }
        else {
            return findPre(R(rt), num);
        }
    }
    
    int findNext(int rt)
    {
        if (L(rt) == 0) {
            return tree[rt].v;
        }
        else {
            return findNext(L(rt));
        }
    }
    
    int main()
    {
        int pos, ans, pre, next, sum;
        while (scanf("%d", &N) == 1) {
            sum = 0;
            for (int i = 1; i <= N; ++i) {
                scanf("%d", &seq[i]);
            }
            init();
            if (N >= 1) {
                sum += seq[1];
            }
            for (int i = 1; i <= N; ++i) {
                ans = INF;
                pos = insert(rt, seq[i], tree[rt].fa);
                splay(pos, 0);  // 这个操作会将pos节点变成根节点
                if (L(rt)) {
                    pre = findPre(L(rt), seq[i]);
                    ans = abs(seq[i] - pre);
                }
                if (R(rt)) {
                    next = findNext(R(rt));
                    ans = min(abs(next - seq[i]), ans);
                }
                sum += ans;
            }
            printf("%d\n", sum);
        }
        return 0;
    }
  • 相关阅读:
    包 (package)
    Object类
    异常
    接口
    抽象类
    多态(经典案例)
    三大特性:(经典代码)
    对象创建的过程(重点理解)
    final关键字
    cocos2dx工程中接入支付宝sdk
  • 原文地址:https://www.cnblogs.com/Lyush/p/2552583.html
Copyright © 2011-2022 走看看