[BZOJ2947]促销(Splay)

本文介绍了一个用于模拟超市促销活动中奖品成本的程序实现。该程序采用了一种特殊的数据结构来高效地找出并移除每日最大和最小消费金额的账单,从而计算整个促销期间商家需支付的总奖品价值。

Description

Great Bytelandish的超级市场网络请你编写一个程序模拟促销商品的成本费用(simulating costs of the promotionbeing prepared)。推销商品要遵守以下规则:

1. 想参与促销的顾客在自己的帐单上写下个人信息,然后将票据投入一个特制的投票箱中。

2. 促销期间,每天结束后,有2张票据将被取出——消费金额最大的和最小的两张帐单。消费金额最大的那位顾客得到的奖品价值等于取出的2张帐单的差额。

3. 为了避免多次得奖,所有取出的帐单将不再放回箱中,其余的票继续参加促销活动.

由于商场的顾客特别多,所以每天投票箱中都至少有2张帐单。你的任务是计算在促销期间,商家一共要送出多少前的礼品。

Code

#include <cstdio>
#include <algorithm>
#define N 1000010
#define lc(x) T[(x)][0]
using namespace std;

int T[N][2],fa[N],k[N],tot,rt,Ans;

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

void rotate(int p){
    int q=fa[p],y=fa[q],x=(T[q][1]==p);
    T[q][x]=T[p][x^1];fa[T[q][x]]=q;
    T[p][x^1]=q;fa[q]=p;
    fa[p]=y;
    if(y){
        if(T[y][0]==q) T[y][0]=p;
        else if(T[y][1]==q) T[y][1]=p;
    }
}

void splay(int x){
    for(int y;y=fa[x];rotate(x))
        if(fa[y]) rotate((x==lc(y))==(y==lc(fa[y]))?y:x);
    rt=x;
}

void Insert(int x,int v){
    if(!rt){
        rt=++tot;
        T[rt][0]=T[rt][1]=0;
        fa[rt]=0;
        k[rt]=v;
        return;
    }
    int y;
    for(;;){
        y=T[x][k[x]<v];
        if(!y){
            y=++tot;
            k[y]=v;
            T[y][0]=T[y][1]=0;
            fa[y]=x;
            T[x][k[x]<v]=y;
            break;
        }
        x=y;
    }
    splay(y);
}

void Del(int x){
    splay(x);
    if(T[x][0]*T[x][1]==0) rt=T[x][0]+T[x][1];
    else{
        int t=T[x][1];
        while(T[t][0]) t=T[t][0];
        T[t][0]=T[x][0],fa[T[t][0]]=t;
        rt=T[x][1];
    }
    fa[rt]=0;
}

int f(int x,int b){
    while(T[x][b]) x=T[x][b];
    int r=k[x];
    Del(x);
    return r;
}

int main(){
    int day=read();
    while(day--){
        int n=read();
        while(n--) Insert(rt,read());
        Ans+=f(rt,1)-f(rt,0);
    }
    printf("%d\n",Ans);
    return 0;
}

转载于:https://www.cnblogs.com/void-f/p/8390559.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值