zoukankan      html  css  js  c++  java
  • HYSBZ 1588 营业额统计

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1588

    题意:详见题面,中文

    思路:平衡树的模板题。 可用Treap,Splay,Scapegoat Tree

    【替罪羊树代码】

    #define _CRT_SECURE_NO_DEPRECATE
    #include<stdio.h>  
    #include<string.h>  
    #include<cstring>
    #include<algorithm>  
    #include<queue>  
    #include<math.h>  
    #include<time.h>
    #include<vector>
    #include<iostream>
    using namespace std;
    typedef long long int LL;
    const int INF = 0x3f3f3f3f;
    typedef long long LL;
    namespace Scapegoat_Tree {
    #define MAXN (1000000 + 10)
        const double alpha = 0.75;
        struct Node {
            Node * ch[2];
            int key, size, cover; // size为有效节点的数量,cover为节点总数量 
            bool exist;    // 是否存在(即是否被删除) 
            void PushUp(void) {
                size = ch[0]->size + ch[1]->size + (int)exist;
                cover = ch[0]->cover + ch[1]->cover + 1;
            }
            bool isBad(void) { // 判断是否需要重构 
                return ((ch[0]->cover > cover * alpha + 5) ||
                    (ch[1]->cover > cover * alpha + 5));
            }
        };
        struct STree {
        protected:
            Node mem_poor[MAXN]; //内存池,直接分配好避免动态分配内存占用时间 
            Node *tail, *root, *null; // 用null表示NULL的指针更方便,tail为内存分配指针,root为根 
            Node *bc[MAXN]; int bc_top; // 储存被删除的节点的内存地址,分配时可以再利用这些地址 
    
            Node * NewNode(int key) {
                Node * p = bc_top ? bc[--bc_top] : tail++;
                p->ch[0] = p->ch[1] = null;
                p->size = p->cover = 1; p->exist = true;
                p->key = key;
                return p;
            }
            void Travel(Node * p, vector<Node *>&v) {
                if (p == null) return;
                Travel(p->ch[0], v);
                if (p->exist) v.push_back(p); // 构建序列 
                else bc[bc_top++] = p; // 回收 
                Travel(p->ch[1], v);
            }
            Node * Divide(vector<Node *>&v, int l, int r) {
                if (l >= r) return null;
                int mid = (l + r) >> 1;
                Node * p = v[mid];
                p->ch[0] = Divide(v, l, mid);
                p->ch[1] = Divide(v, mid + 1, r);
                p->PushUp(); // 自底向上维护,先维护子树 
                return p;
            }
            void Rebuild(Node * &p) {
                static vector<Node *>v; v.clear();
                Travel(p, v); p = Divide(v, 0, v.size());
            }
            Node ** Insert(Node *&p, int val) {
                if (p == null) {
                    p = NewNode(val);
                    return &null;
                }
                else {
                    p->size++; p->cover++;
    
                    // 返回值储存需要重构的位置,若子树也需要重构,本节点开始也需要重构,以本节点为根重构 
                    Node ** res = Insert(p->ch[val >= p->key], val);
                    if (p->isBad()) res = &p;
                    return res;
                }
            }
            void Erase(Node *p, int id) {
                p->size--;
                int offset = p->ch[0]->size + p->exist;
                if (p->exist && id == offset) {
                    p->exist = false;
                    return;
                }
                else {
                    if (id <= offset) Erase(p->ch[0], id);
                    else Erase(p->ch[1], id - offset);
                }
            }
        public:
            void Init(void) {
                tail = mem_poor;
                null = tail++;
                null->ch[0] = null->ch[1] = null;
                null->cover = null->size = null->key = 0;
                root = null; bc_top = 0;
            }
            STree(void) { Init(); }
    
            void Insert(int val) {
                Node ** p = Insert(root, val);
                if (*p != null) Rebuild(*p);
            }
            int Rank(int val) { //相同值取最小的排名
                Node * now = root;
                int ans = 1;
                while (now != null) { // 非递归求排名 
                    if (now->key >= val) now = now->ch[0];
                    else {
                        ans += now->ch[0]->size + now->exist;
                        now = now->ch[1];
                    }
                }
                return ans;
            }
            int Kth(int k) { //支持相同值
                Node * now = root;
                while (now != null) { // 非递归求第K大 
                    if (now->ch[0]->size + 1 == k && now->exist) return now->key;
                    else if (now->ch[0]->size >= k) now = now->ch[0];
                    else k -= now->ch[0]->size + now->exist, now = now->ch[1];
                }
            }
            void Erase(int k) {
                Erase(root, Rank(k));
                if (root->size < alpha * root->cover) Rebuild(root);
            }
            void Erase_kth(int k) {
                Erase(root, k);
                if (root->size < alpha * root->cover) Rebuild(root);
            }
        };
    #undef MAXN
    }
    using namespace Scapegoat_Tree;
    STree Scapegoat;
    int main(){
        #ifdef kirito
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        //    int start = clock();
        int n,val;
        while (~scanf("%d", &n)){
            LL sum=0;
            for (int i = 1; i <= n; i++){
                scanf("%d", &val);
                if (i == 1){
                    sum += val;
                }
                else{
                    int valRank = Scapegoat.Rank(val);
                    int a = abs(Scapegoat.Kth(valRank) - val);
                    int b = abs(Scapegoat.Kth(valRank - 1) - val);
                    int c = abs(Scapegoat.Kth(val + 1) - val);
                    sum += min(a, min(b, c));
                }
                Scapegoat.Insert(val);
            }
            printf("%d
    ", sum);
            /* DEBUG INFO
            vector<Node *> xx;
            _t.Travel(_t.root, xx);
            cout << "::";
            for(int i = 0; i < xx.size(); i++) cout << xx[i]->key << ' '; cout << endl;
            */
        }
        //#ifdef LOCAL_TIME
        //    cout << "[Finished in " << clock() - start << " ms]" << endl;
        //#endif
        return 0;
    }

    【Splay代码】

    #define _CRT_SECURE_NO_DEPRECATE
    #include<stdio.h>  
    #include<string.h>  
    #include<cstring>
    #include<algorithm>  
    #include<queue>  
    #include<math.h>  
    #include<time.h>
    #include<vector>
    #include<iostream>
    using namespace std;
    typedef long long int LL;
    const int MAXN = 1e6 + 5;
    const int INF = 0x3f3f3f3f;
    int cnt, rt;
    struct Tree
    {
        int key, size, fa, son[2];
        void set(int _key, int _size, int _fa)
        {
            key = _key;
            size = _size;
            fa = _fa;
            son[0] = son[1] = 0;
        }
    }T[MAXN];
    
    inline void PushUp(int x)
    {
        T[x].size = T[T[x].son[0]].size + T[T[x].son[1]].size + 1;
    }
    
    inline void Rotate(int x, int p) 
    {
        int y = T[x].fa;
        T[y].son[!p] = T[x].son[p];
        T[T[x].son[p]].fa = y;
        T[x].fa = T[y].fa;
        if (T[x].fa)
            T[T[x].fa].son[T[T[x].fa].son[1] == y] = x;
        T[x].son[p] = y;
        T[y].fa = x;
        PushUp(y);
        PushUp(x);
    }
    
    void Splay(int x, int To) 
    {
        while (T[x].fa != To)
        {
            if (T[T[x].fa].fa == To)
                Rotate(x, T[T[x].fa].son[0] == x);
            else
            {
                int y = T[x].fa, z = T[y].fa;
                int p = (T[z].son[0] == y);
                if (T[y].son[p] == x)
                    Rotate(x, !p), Rotate(x, p); 
                else
                    Rotate(y, p), Rotate(x, p); 
            }
        }
        if (To == 0) rt = x;
    }
    
    int find(int key) 
    {
        int x = rt;
        while (x && T[x].key != key)
            x = T[x].son[key > T[x].key];
        if (x) Splay(x, 0);
        return x;
    }
    
    int prev() 
    {
        int x = T[rt].son[0];
        if (!x) return 0;
        while (T[x].son[1])
            x = T[x].son[1];
        //Splay(x, 0);
        return x;
    }
    
    int succ() 
    {
        int x = T[rt].son[1];
        if (!x) return 0;
        while (T[x].son[0])
            x = T[x].son[0];
        //Splay(x, 0);
        return x;
    }
    
    void Insert(int key) 
    {
        if (!rt)
            T[rt = cnt++].set(key, 1, 0);
        else
        {
            int x = rt, y = 0;
            while (x)
            {
                y = x;
                x = T[x].son[key > T[x].key];
            }
            T[x = cnt++].set(key, 1, y);
            T[y].son[key > T[y].key] = x;
            Splay(x, 0);
        }
    }
    
    void Delete(int key) 
    {
        int x = find(key);
        if (!x) return;
        int y = T[x].son[0];
        while (T[y].son[1])
            y = T[y].son[1];
        int z = T[x].son[1];
        while (T[z].son[0])
            z = T[z].son[0];
        if (!y && !z)
        {
            rt = 0;
            return;
        }
        if (!y)
        {
            Splay(z, 0);
            T[z].son[0] = 0;
            PushUp(z);
            return;
        }
        if (!z)
        {
            Splay(y, 0);
            T[y].son[1] = 0;
            PushUp(y);
            return;
        }
        Splay(y, 0);
        Splay(z, y);
        T[z].son[0] = 0;
        PushUp(z);
        PushUp(y);
    }
    
    int GetPth(int p) 
    {
        if (!rt) return 0;
        int x = rt, ret = 0;
        while (x)
        {
            if (p == T[T[x].son[0]].size + 1)
                break;
            if (p>T[T[x].son[0]].size + 1)
            {
                p -= T[T[x].son[0]].size + 1;
                x = T[x].son[1];
            }
            else
                x = T[x].son[0];
        }
        Splay(x, 0);
        return x;
    }
    
    int GetRank(int key) 
    {
        if (!rt) return 0;
        int x = rt, ret = 0, y;
        while (x)
        {
            y = x;
            if (T[x].key <= key)
            {
                ret += T[T[x].son[0]].size + 1;
                x = T[x].son[1];
            }
            else
                x = T[x].son[0];
        }
        Splay(y, 0);
        return ret;
    }
    int main(){
        //#ifdef kirito
        //    freopen("in.txt","r",stdin);
        //    freopen("out.txt","w",stdout);
        //#endif
        //    int start = clock();
        int n;
        while (~scanf("%d", &n)){
            LL ans = 0; rt = 0; cnt = 1; T[0].set(INF, 1, 0);
            for (int i = 1; i <= n; i++){
                int val; scanf("%d", &val);
                Insert(val);
                if (i == 1){ ans = val; }
                else{
                    ans += min(abs(val - T[succ()].key), abs(val - T[prev()].key));
                }
            }
            printf("%lld
    ", ans);
        }
        //#ifdef LOCAL_TIME
        //    cout << "[Finished in " << clock() - start << " ms]" << endl;
        //#endif
        return 0;
    }
  • 相关阅读:
    相机振动效果(打击屏幕振动)
    Unity3d Shader开发(一)Properties
    指定字符串长度,并对多余的填充
    Render Texture的使用(截取rendertexture的一帧到Texture2D)
    拖尾渲染器 Trail Renderer
    角色控制器 Character Controller
    Spring Boot 的单元测试
    Git 常用命令整理
    孔浩老师的 Struts2 教程听课笔记(思维导图)
    Java 设计模式之 Command 设计模式
  • 原文地址:https://www.cnblogs.com/kirito520/p/5913171.html
Copyright © 2011-2022 走看看