首页 > 代码库 > BZOJ 1588: [HNOI2002]营业额统计 双向链表 / splay / treap

BZOJ 1588: [HNOI2002]营业额统计 双向链表 / splay / treap

1588: [HNOI2002]营业额统计

 

Description

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

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


该题数据bug已修复.----2016.5.15

 

题解:

  双向链表:http://www.open-open.com/doc/view/a46375420b6a43f08e0862489069a11d

技术分享
#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>#include<queue>using namespace std;#pragma comment(linker, "/STACK:102400000,102400000")#define ls i<<1#define rs ls | 1#define mid ((ll+rr)>>1)typedef long long LL;const LL INF = (1LL<<60)-1;const double Pi = acos(-1.0);const int N = 1e5+10, M = 1e6+11, mod = 1e9+7, inf = (1<<30)-1;struct ss {int x,id;    bool operator < (const ss &r) const    {        return x<r.x;    }}a[N];int ans,n,Rank[N],lef[N],righ[N];int main() {        scanf("%d",&n);        for(int i = 1; i <= n; ++i) scanf("%d",&a[i].x),a[i].id=i;        ans = a[1].x;        sort(a+1,a+n+1);        for(int i = 1; i <= n; ++i) Rank[a[i].id] = i;        for(int i = 1; i <= n; ++i) lef[i] = i-1, righ[i] = i+1;        righ[n] = 0;        for(int i = n; i >=1; --i) {                int x = Rank[i];                if(lef[x] && righ[x]) {                    ans += min(a[x].x - a[lef[x]].x,a[righ[x]].x - a[x].x);                    righ[lef[x]] = righ[x];                    lef[righ[x]] = lef[x];                } else if(!lef[x] && righ[x]) {                    ans += a[righ[x]].x - a[x].x;                    lef[righ[x]] = 0;                } else if(!righ[x] && lef[x]){                    ans += a[x].x - a[lef[x]].x;                    righ[lef[x]] = 0;                }        }        printf("%d\n",ans);}
双向链表

   treap写法

技术分享
#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>#include<queue>using namespace std;#pragma comment(linker, "/STACK:102400000,102400000")#define ls i<<1#define rs ls | 1#define mid ((ll+rr)>>1)typedef long long LL;const LL INF = (1LL<<60)-1;const double Pi = acos(-1.0);const int N = 1e5+10, M = 1e6+11, mod = 1e9+7, inf = (1<<30)-1;struct data {int l,r,v,size,rnd,w;}tr[N * 20];int n,size=0,root,ans,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 query_pre(int k,int x) {        if(k == 0) return ;        if(tr[k].v <= x) {            ans=tr[k].v;query_pre(tr[k].r,x);        } else query_pre(tr[k].l,x);}void query_nex(int k,int x) {        if(k == 0) return ;        if(tr[k].v >= x) {            ans=tr[k].v;;query_nex(tr[k].l,x);        } else query_nex(tr[k].r,x);}int main() {        root = 0;        scanf("%d",&n);        for(int i = 1; i <= n; ++i) {            int x;            scanf("%d",&x);            if(i == 1) {                Ans = x;            } else {                ans = -inf;query_pre(root,x);                int fi = ans;                ans = inf;query_nex(root,x);                int se = ans;                //cout<<fi<<" "<<se<<endl;               if(fi!=-inf || se != inf) Ans += min(x-fi,se-x);            }            insert(root,x);        }        printf("%d\n",Ans);        return 0;}
treap

 

BZOJ 1588: [HNOI2002]营业额统计 双向链表 / splay / treap