• BZOJ 1588: Treap 模板


    1588: [HNOI2002]营业额统计

    Time Limit: 5 Sec  Memory Limit: 162 MB
    Submit: 12171  Solved: 4352

    Description

    营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。  输入输出要求

    最小波动值= min { | 该天以前某一天的营业额-该天的营业额 | }

    Input

    第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。

    Output

    输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。

    Sample Input

    6
    5
    1
    2
    5
    4
    6

    Sample Output

    12

    HINT

    结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12

    SOLUTION:

    可以用TREAP,在读入当天的营业额x后,先求出x的前驱(前驱定义为小于x,且最大的数)和x的后继(后继定义为大于x,且最小的数),

    后分别与X相减求出较小的绝对值。最后插入X。

    另,数据有问题,在读入时要:if (scanf ("%d", &x) == EOF) x = 0;

    AC代码:

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <vector>
    using namespace std;
    
    int size=0;
    
    struct data
    {
        int l,size,r,w,rnd,val;
    } tr[1000005];
    int n;
    int root;
    
    int _abs(int x)
    {
        if (x>0) return x;
        return (0-x);
    }
    
    int _min(int a,int b)
    {
        if (a<b) return a;
        return b;
    }
    
    void update(int &k)
    {
        tr[k].size=tr[tr[k].l ].size+tr[tr[k].r ].size+ tr[k].w;
    }
    
    void lturn(int &k)
    {
        int t=tr[k].r;tr[k].r=tr[t].l;tr[t].l=k;
        tr[t].size=tr[k].size;update(k);k=t;
    }
    
    void rturn(int &k)
    {
        int t=tr[k].l;tr[k].l=tr[t].r;tr[t].r=k;
        tr[t].size=tr[k].size;update(k);k=t;
    }
    
    void insert(int &k,int x)
    {
        if (k==0)    
        {
            size++;k=size;
            tr[k].size=tr[k].w=1;
            tr[k].rnd=rand();
            tr[k].val=x;
            return;
        }
        tr[k].size++;
        if (tr[k].val==x)
        {
            tr[k].w++;
        }
        else
        {
            if (x>tr[k].val) 
            {
                insert(tr[k].r,x);
                if (tr[tr[k].r].rnd<tr[k].rnd) lturn(k);
            }
            else 
            {
                insert(tr[k].l,x);
                if (tr[tr[k].l].rnd<tr[k].rnd ) rturn(k);
            }
        }    
    }
    
    int ans=0;
    
    void query_pro(int k,int x)
    {
        if (k==0) return ;
        if (tr[k].val==x) 
        {
            ans=x;
            return ;
        }
        if (tr[k].val<x)
        {
            ans=tr[k].val;query_pro(tr[k].r,x);
            }    
        else
            query_pro(tr[k].l,x);
    }
    
    void query_sub(int k,int x)
    {
        if (k==0) return ;
        if (tr[k].val==x) {
            ans=x;
            return;
        }
        if (tr[k].val>x)
        {
            ans=tr[k].val;query_sub(tr[k].l,x);
        }
        else
            query_sub(tr[k].r,x);
    }
    
    
    int main()
    {
        
        scanf("%d",&n);
        int x;
        long long sum=0;
        for (int i=1;i<=n;i++)
        {
            if (scanf ("%d", &x) == EOF) x = 0;
            if (i!=1)
            {
                ans=-1000000000;
                query_pro(root,x);
                int flow_pro=_abs(x-ans);
                ans=-1000000000;
                query_sub(root,x);
                int flow_sub=_abs(x-ans);
                sum+=(long long)_min(flow_pro,flow_sub);    
             }
            else sum+=(long long)x;
            insert(root,x);
        }
        
        printf("%d",(int)sum);
        
        return 0;        
    } 

    更多解法:http://hzwer.com/1276.html

    TREAP模板:[from baidu qaq]

    http://baike.baidu.com/link?url=L0NLqoR1SDZsk7iX5ZJZb0yt6qukm7a18e5IxBdPFUVaueBoLAHv5m8HmnPzUCXzHO764KOdv_xCU7yfvH_vea

    支持以下操作
    1. 插入x数
    2. 删除x数(若有多个相同的数,因只删除一个)
    3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数)
    6. 求x的后继(后继定义为大于x,且最小的数)
    //by hzwer
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    struct data{
        int l,r,v,size,rnd,w;
    }tr[100005];
    int n,size,root,ans;
    void update(int k)//更新结点信息
    {
        tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w;
    }
    void rturn(int &k)
    {
        int t=tr[k].l;tr[k].l=tr[t].r;tr[t].r=k;
        tr[t].size=tr[k].size;update(k);k=t;
    }
    void lturn(int &k)
    {
        int t=tr[k].r;tr[k].r=tr[t].l;tr[t].l=k;
        tr[t].size=tr[k].size;update(k);k=t;
    }
    void insert(int &k,int x)
    {
        if(k==0)
        {
            size++;k=size;
            tr[k].size=tr[k].w=1;tr[k].v=x;tr[k].rnd=rand();
            return;
        }
        tr[k].size++;
        if(tr[k].v==x)tr[k].w++;
        else if(x>tr[k].v)
        {
            insert(tr[k].r,x);
            if(tr[tr[k].r].rnd<tr[k].rnd)lturn(k);
        }
        else 
        {
            insert(tr[k].l,x);
            if(tr[tr[k].l].rnd<tr[k].rnd)rturn(k);
        } 
    }
    void del(int &k,int x)
    {
        if(k==0)return; 
        if(tr[k].v==x)
        {
            if(tr[k].w>1)
            {
                tr[k].w--;tr[k].size--;return;
            }
            if(tr[k].l*tr[k].r==0)k=tr[k].l+tr[k].r;
            else if(tr[tr[k].l].rnd<tr[tr[k].r].rnd)
                rturn(k),del(k,x);
            else lturn(k),del(k,x);
        }
        else if(x>tr[k].v)
            tr[k].size--,del(tr[k].r,x);
        else tr[k].size--,del(tr[k].l,x);
    }
    int query_rank(int k,int x)
    {
        if(k==0)return 0;
        if(tr[k].v==x)return tr[tr[k].l].size+1;
        else if(x>tr[k].v)
            return tr[tr[k].l].size+tr[k].w+query_rank(tr[k].r,x);
        else return query_rank(tr[k].l,x);
    }
    int query_num(int k,int x)
    {
        if(k==0)return 0;
        if(x<=tr[tr[k].l].size)
            return query_num(tr[k].l,x);
        else if(x>tr[tr[k].l].size+tr[k].w)
            return query_num(tr[k].r,x-tr[tr[k].l].size-tr[k].w);
        else return tr[k].v;
    }
    void query_pro(int k,int x)
    {
        if(k==0)return;
        if(tr[k].v<x)
        {
            ans=k;query_pro(tr[k].r,x);
        }
        else query_pro(tr[k].l,x);
    }
    void query_sub(int k,int x)
    {
        if(k==0)return;
        if(tr[k].v>x)
        {
            ans=k;query_sub(tr[k].l,x);
        }
        else query_sub(tr[k].r,x);
    }
    int main()
    {
        scanf("%d",&n);
        int opt,x;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&opt,&x);
            switch(opt)
            {
            case 1:insert(root,x);break;
            case 2:del(root,x);break;
            case 3:printf("%d
    ",query_rank(root,x));break;
            case 4:printf("%d
    ",query_num(root,x));break;
            case 5:ans=0;query_pro(root,x);printf("%d
    ",tr[ans].v);break;
            case 6:ans=0;query_sub(root,x);printf("%d
    ",tr[ans].v);break;
            }
        }
        return 0;
    }
  • 相关阅读:
    根据字符串拆分字符串
    .NET WinForm读取扫描枪从COM口传过来的数据,显示在TextBox中,并做其他操作。
    《将博客搬至CSDN》
    mysql学习(二)DML
    mysql学习(一)DDL
    BigDecimal
    排序
    2017
    oracle的mapper小结
    数据结构查找
  • 原文地址:https://www.cnblogs.com/sllr15/p/5202484.html
Copyright © 2020-2023  润新知