HYSBZ 1588 营业额统计

Posted キリト

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\\n", 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\\n", ans);
    }
    //#ifdef LOCAL_TIME
    //    cout << "[Finished in " << clock() - start << " ms]" << endl;
    //#endif
    return 0;
}

 

以上是关于HYSBZ 1588 营业额统计的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1588: [HNOI2002]营业额统计

BZOJ1588_营业额统计_KEY

BZOJ-1588营业额统计 Splay

bzoj1588: [HNOI2002]营业额统计 splay瞎写

bzoj1588: [HNOI2002]营业额统计

链表BZOJ1588: [HNOI2002]营业额统计