【bzoj1588 营业额统计】

题目大意:

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

输入输出要求:

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

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

样例输入:

  6
  5
  1
  2
  5
  4
  6

样例输出:

  12

题解:

  splay第一题模板真的很丑,为了把所有操作写清楚,代码以后还会去优化。

  用splay维护每次加入一个数,把第一个比它大或者小的数取出来。每次把这个数splay到root位置,然后把根节点leftson的子树中最右与rightson的子树中最左的节点取出来比较。如果在insert时有一样的数就可以直接return.(之前有出现这个数对答案贡献为0)

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 using namespace std;
  6 int cnt,root,ans,fl;
  7 struct node
  8 {
  9     int fa,l,r,sum;
 10 }    tr[100005];
 11 inline void leftrotate(int x)
 12 {
 13     int y=tr[x].fa;int z=tr[y].fa;
 14     tr[y].r=tr[x].l;
 15     if(tr[x].l!=-1)    tr[tr[x].l].fa=y;
 16     tr[x].fa=z;
 17     if(z!=-1)
 18     {
 19         if(tr[z].l==y)    tr[z].l=x;
 20         else    tr[z].r=x;
 21     }
 22     tr[x].l=y;tr[y].fa=x;
 23 }
 24 inline void rightrotate(int x)
 25 {
 26     int y=tr[x].fa;int z=tr[y].fa;
 27     tr[y].l=tr[x].r;
 28     if(tr[x].r!=-1)    tr[tr[x].r].fa=y;
 29     tr[x].fa=z;
 30     if(z!=-1)
 31     {
 32         if(tr[z].l==y)    tr[z].l=x;
 33         else    tr[z].r=x;
 34     }
 35     tr[x].r=y;tr[y].fa=x;
 36 }
 37 inline void splay(int x)
 38 {
 39     while(tr[x].fa!=-1)
 40     {
 41         int y=tr[x].fa;int z=tr[y].fa;
 42         if(z==-1)
 43         {
 44             if(tr[y].l==x)    rightrotate(x);
 45             else    leftrotate(x);
 46         }
 47         else
 48         {
 49             if(tr[z].l==y && tr[y].l==x)
 50             {
 51                 rightrotate(y);
 52                 rightrotate(x);
 53             }
 54             else    if(tr[z].l==y && tr[y].r==x)
 55             {
 56                 leftrotate(x);
 57                 rightrotate(x);
 58             }
 59             else    if(tr[z].r==y && tr[y].l==x)
 60             {
 61                 rightrotate(x);
 62                 leftrotate(x);
 63             }
 64             else
 65             {
 66                 leftrotate(y);
 67                 leftrotate(x);
 68             }
 69         }
 70     }
 71     root=x;
 72 }
 73 inline int ls(int x)
 74 {
 75     int y=tr[x].l;
 76     if(y==-1)    return y;
 77     while(tr[y].r!=-1)    y=tr[y].r;
 78     return y;
 79 }
 80 inline int nx(int x)
 81 {
 82     int y=tr[x].r;
 83     if(y==-1)    return y;
 84     while(tr[y].l!=-1)    y=tr[y].l;
 85     return y;
 86 }
 87 inline void search(int x,int now)
 88 {
 89     if(x==tr[now].sum)
 90     {
 91         fl=0;
 92         return;
 93     }
 94     if(x<tr[now].sum)
 95     {
 96         if(tr[now].l==-1)
 97         {
 98             tr[now].l=cnt,tr[cnt].fa=now,tr[cnt].l=tr[cnt].r=-1;
 99             tr[cnt].sum=x;
100         }
101         else    search(x,tr[now].l);
102     }
103     else
104     {
105         if(tr[now].r==-1)
106         {
107             tr[now].r=cnt,tr[cnt].fa=now,tr[cnt].l=tr[cnt].r=-1;
108             tr[cnt].sum=x;
109         }
110         else    search(x,tr[now].r);
111     }
112 }
113 inline void insert(int x)
114 {
115     fl=1;cnt++;
116     search(x,root);
117     if(!fl)    return;
118     splay(cnt);
119     int last=ls(cnt),next=nx(cnt);
120     int minn=1e9+7;
121     if(last!=-1)    minn=min(minn,abs(tr[last].sum-x));
122     if(next!=-1)    minn=min(minn,abs(tr[next].sum-x));
123     ans+=minn;
124 }
125 int main()
126 {
127     int n,x;
128     while(scanf("%d",&n)!=-1)
129     {
130         cnt=0;
131         scanf("%d",&x);
132         ans=x;tr[++cnt].fa=-1;
133         tr[cnt].sum=x;
134         root=cnt;
135         tr[cnt].l=tr[cnt].r=-1;
136         for(int i=1;i<n;i++)
137         {
138             scanf("%d",&x);
139             insert(x);
140         }
141         printf("%d",ans);
142     }
143     return 0;
144 } 

 

转载于:https://www.cnblogs.com/Dndlns/p/7861581.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值