Description
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。 输入输出要求
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i
天公司的营业额。
天数n<=32767,
每天的营业额ai <= 1,000,000。
最后结果T<=2^31
Output
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。
Sample Input
6
5
1
2
5
4
6
5
1
2
5
4
6
Sample Output
12
平衡树裸题,求前驱和后继即可,然后再插入进去就好了
好像是Treap比较快?还是我打的替罪羊比较傻。
Treap:
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int n,Ans;
struct node{
int v,r,s;
node *ch[2];
void Maintain(){
#define size(x) ((x)?(x)->s :0)
s = size(ch[0])+size(ch[1])+1;
}
int cmp(int x)const{
if(x==v)return -1;
return x<v?0:1;
}
node(){
v=r=s=0;
ch[0]=ch[1]=NULL;
}
node(int x);
}*root,*null=new node();
node :: node(int x){
v=x;r=rand();s=1;
ch[0]=ch[1]=null;
}
void rotate(node *&o,int d){
node *k=o->ch[d^1];
o->ch[d^1]=k->ch[d];
k->ch[d]=o;
o->Maintain();
k->Maintain();
o=k;
}
int Rank(int x){
node * o =root;
int Ans=0;
while(o!=null){
if(o->v>=x)o=o->ch[0];
else Ans+=o->ch[0]->s+1,o=o->ch[1];
}
return Ans+1;
}
int kth(int k){
node *o=root;
while(o!=null){
if(k==o->ch[0]->s+1)return o->v;
else if(k<=o->ch[0]->s)o=o->ch[0];
else k-=o->ch[0]->s+1,o=o->ch[1];
}
return inf;
}
void insert(node *&o,int x){
if(o==null)o=new node(x);
else {
int d = x<o->v ?0:1;
insert(o->ch[d],x);
if(o->ch[d]->r >o->r)rotate(o,d^1);
}
o->Maintain();
}
int next(int x){
return kth(Rank(x));
}
int pre(int x){
return kth(Rank(x)-1);
}
int main(){
srand(time(NULL));
freopen("turnover.in","r",stdin);
freopen("turnover.out","w",stdout);
root = null;
scanf("%d",&n);
int w;
scanf("%d",&w);
Ans += w;
insert(root,w);
while(--n){
scanf("%d",&w);
Ans += min(abs(next(w)-w),abs(pre(w)-w));
insert(root,w);
}
printf("%d\n",Ans);
}
替罪羊:
#include <bits/stdc++.h>
using namespace std;
const double alpha = 0.755;
const int MAXN = 102767;
int len,n,Ans;
struct node{
int v,s,cover,ex;
node *ch[2];
bool bad(){
return ch[0]->cover >= cover * alpha || ch[1]->cover >= cover * alpha;
}
void Maintain(){
s = ch[0]->s+ch[1]->s+ex;
cover = ch[0]->cover + ch[1]->cover + 1;
}
node(){
v=s=cover=ex=0;
ch[0]=ch[1]=NULL;
}
node(int x);
void *operator new (size_t);
}*null=new node(),*lst[MAXN],*C,*mem,*root;
void* node :: operator new (size_t){
if(C==mem){
C = new node [1<<15];
mem = C + (1<<15);
}
return C++;
}
node :: node(int x){
v=x;
s=cover=ex=1;
ch[0]=ch[1]=null;
}
void travel(node *p){
if(p==null)return;
travel(p->ch[0]);
if(p->ex)lst[++len]=p;
else delete p;
travel(p->ch[1]);
}
node* divide(int l,int r){
if(l>r)return null;
int m = l+r>>1;
lst[m]->ch[0]=divide(l,m-1);
lst[m]->ch[1]=divide(m+1,r);
lst[m]->Maintain();
return lst[m];
}
void rebuild(node *&o){
len = 0;
travel(o);
o = divide(1,len);
}
node ** insert(node *&o,int x){
if(o==null){
o = new node(x);
return &null;
}
node **p=insert(o->ch[o->v<=x],x);
if(o->bad())p=&o;
o->Maintain();
return p;
}
void Tree_insert(int x){
node **p=insert(root,x);
if(*p!=null)rebuild(*p);
}
int Rank(int x){
node *o = root;
int Ans = 1;
while(o!=null){
if(o->v>=x)o = o->ch[0];
else Ans += o->ch[0]->s+o->ex,o=o->ch[1];
}
return Ans;
}
int kth(int k){
node *o = root;
while(o!=null){
if(k == o->ch[0]->s+1 && o->ex)return o->v;
else if(k<=o->ch[0]->s)o=o->ch[0];
else k-=o->ch[0]->s+o->ex,o=o->ch[1];
}
}
int pre(int x){
return kth(Rank(x)-1);
}
int next(int x){
return kth(Rank(x));
}
int main(){
freopen("turnover.in","r",stdin);
freopen("turnover.out","w",stdout);
root = null;
scanf("%d",&n);
int w = 0;
scanf("%d",&w);
Ans += w;
Tree_insert(w);
n--;
while(n--){
scanf("%d",&w);
Ans += min(abs(next(w)-w),abs(pre(w)-w));
Tree_insert(w);
}
printf("%d\n",Ans);
}