P2234 [HNOI2002]营业额统计 (权值线段树)

Posted 心之所向 素履以往

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2234 [HNOI2002]营业额统计 (权值线段树)相关的知识,希望对你有一定的参考价值。

P2234 [HNOI2002]营业额统计

题目描述

Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。

Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:

当最小波动值越大时,就说明营业情况越不稳定。

而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。

第一天的最小波动值为第一天的营业额。

输入输出格式

输入格式:

 

输入由文件’turnover.in’读入。

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

 

输出格式:

 

技术分享

 

输入输出样例

输入样例#1:
6
5
1
2
5
4
6
输出样例#1:
12

说明

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

 

可以用splay做

这里写的权值线段树

把点离散化 

以权值为下标建立一颗线段树

然后考虑每一个点

我们需要在这个点的前面(也就是在比这个点小的所有点中)找一个最大的

再在这个点的后面(也就是比这个点小的所有点中)找一个最小的

那么把得到的这两个值分别与这个点的值做差,

再取最小值。

这个值就应该是答案

累加

 

技术分享
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #define MAXN 50010
  5 
  6 using namespace std;
  7 
  8 const int INF=0x7fffffff;
  9 
 10 struct node {
 11     int l,r;
 12     int mx,mn;
 13 };
 14 node t[MAXN<<2];
 15 
 16 struct data {
 17     int ord,x;
 18     bool operator < (const data b) const {
 19         return x<b.x;
 20     }
 21 };
 22 data e[MAXN];
 23 
 24 int n;
 25 
 26 int d[MAXN],a[MAXN];
 27 
 28 inline void read(int &x) {
 29     int f=1;x=0;char c=getchar();
 30     while(c>9||c<0) {if(c==-) f=-1;c=getchar();}
 31     while(c>=0&&c<=9) {x=(x<<1)+(x<<3)+c-48;c=getchar();}
 32     x=x*f;
 33 }
 34 
 35 inline void pushup(int now) {
 36     t[now].mx=max(t[now<<1].mx,t[now<<1|1].mx);
 37     t[now].mn=min(t[now<<1].mn,t[now<<1|1].mn);
 38 }
 39 
 40 void build_tree(int now,int l,int r) {
 41     t[now].l=l;
 42     t[now].r=r;
 43     if(t[now].l==t[now].r) {
 44         t[now].mx=-1;
 45         t[now].mn=INF-1;
 46         return;
 47     }
 48     int mid=(l+r)>>1;
 49     build_tree(now<<1,l,mid);
 50     build_tree(now<<1|1,mid+1,r);
 51     pushup(now);
 52 }
 53 
 54 void modify(int now,int x) {
 55     if(t[now].l==t[now].r) {
 56         t[now].mn=t[now].l;
 57         t[now].mx=t[now].l;
 58         return;
 59     }
 60     int mid=(t[now].l+t[now].r)>>1;
 61     if(x<=mid) modify(now<<1,x);
 62     if(x>mid) modify(now<<1|1,x);
 63     pushup(now);
 64 }
 65 
 66 int querymx(int now,int l,int r) {
 67     if(l>r) return -1;
 68     if(l<=t[now].l&&r>=t[now].r) return t[now].mx;
 69     int mid=(t[now].l+t[now].r)>>1;
 70     int ret=-2;
 71     if(l<=mid) ret=max(ret,querymx(now<<1,l,r));
 72     if(r>mid) ret=max(ret,querymx(now<<1|1,l,r));
 73     return ret;
 74 }
 75 
 76 int querymn(int now,int l,int r) {
 77     if(l>r) return INF-1;
 78     if(l<=t[now].l&&r>=t[now].r) return t[now].mn;
 79     int mid=(t[now].l+t[now].r)>>1;
 80     int ret=INF;
 81     if(l<=mid) ret=min(ret,querymn(now<<1,l,r));
 82     if(r>mid) ret=min(ret,querymn(now<<1|1,l,r)); //这里qeurymn写成qeurymx mdzz 
 83     return ret;
 84 } 
 85 
 86 int main() {
 87     read(n);
 88     for(int i=1;i<=n;i++) {
 89         read(a[i]);
 90         e[i].ord=i;
 91         e[i].x=a[i];
 92     }
 93     sort(e+1,e+1+n);
 94     int ord=1;
 95     d[1]=e[1].x;
 96     a[e[1].ord]=ord;
 97     for(int i=2;i<=n;i++) {
 98         if(e[i].x!=e[i-1].x) ord++;
 99         a[e[i].ord]=ord;
100         d[ord]=e[i].x;
101     }
102     build_tree(1,1,ord);
103     int ans=d[a[1]];
104     modify(1,a[1]);
105     for(int i=2;i<=n;i++) {
106         int x=querymx(1,1,a[i]-1);
107         int y=querymn(1,a[i],n);
108         int tmp=INF;
109         if(x!=-1) tmp=min(tmp,d[a[i]]-d[x]);
110         if(y!=INF-1) tmp=min(tmp,d[y]-d[a[i]]);
111         ans+=tmp;
112         modify(1,a[i]);
113     }
114     printf("%d\n",ans);
115     return 0;
116 }
代码

 

以上是关于P2234 [HNOI2002]营业额统计 (权值线段树)的主要内容,如果未能解决你的问题,请参考以下文章

[luogu P2234] [HNOI2002]营业额统计

P2234 [HNOI2002]营业额统计(50分。。。。)

洛谷P2234 [HNOI2002]营业额统计

luogu P2234 [HNOI2002]营业额统计

洛谷:P2234 [HNOI2002]营业额统计

HNOI 2002 营业额统计