HNOI200——营业额统计(splay/treap)
Tiger 最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。Tiger 拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:记该天以前某一天的营业额为 ai,该天营业额为 b,则该天的最小波动值 δ=min|ai−b|δ=min|ai−b|,当最小波动值越大时,就说明营业情况越不稳定。而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助 Tiger 来计算这一个值,第一天的最小波动值为第一天的营业额。
一句话题意 给出一个 n个数的数列{an},对于第 i 个元素 ai,定义 fi=min|ai−aj|fi=min|ai−aj|,其中1≤j<i,f1=a1。求 ∑fi
输入
第一行为正整数,表示该公司从成立一直到现在的天数;接下来的 n 行每行有一个正整数,表示第 i 天公司的营业额 ai
输出
一个正整数,即每一天最小波动的和,结果不超过 2^31
样例输入
6512546
样例输出
12
提示样例说明5+|1−5|+|2−1|+|5−5|+|4−5|+|6−5|=5+4+1+0+1+1=125+|1−5|+|2−1|+|5−5|+|4−5|+|6−5|=5+4+1+0+1+1=12
对于全部数据,1≤n<2^15,
ai≤10^6
很简答的一道题吧。。。。。
splay和treap都可以做
结果tm有个点有负数然而读优没判
卡到心态爆炸
splay写法
#include<bits/stdc++.h>
using namespace std;
int fa[50005],lc[50005],rc[50005],val[50005],cnt,n,root;
inline int read()
{
int x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') {f=-1;c=getchar();}
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
inline int which(int x)
{
return rc[fa[x]]==x;
}
inline void add(int &x,int fat,int valu)
{
x=++cnt,fa[x]=fat,val[x]=valu;
}
inline void rotate(int x)
{
int v=fa[x],z=fa[v];
int b=x==rc[v]?lc[x]:rc[x];
fa[x]=z,fa[v]=x;
if(b) fa[b]=v;
if(z) (lc[z]==v?lc[z]:rc[z])=x;
if(x==lc[v]) rc[x]=v,lc[v]=b;
else lc[x]=v,rc[v]=b;
}
inline void splay(int x)
{
while(fa[x])
{
if(fa[fa[x]])
{
if(which(x)==which(fa[x])) rotate(fa[x]);
else rotate(x);
}
rotate(x);
}
root=x;
}
inline bool insert(int v)
{
int u=root;
while(v>val[u]?rc[u]:lc[u])
{
if(v==val[u]) {splay(u);return false;}
u=v>val[u]?rc[u]:lc[u];
}
if(v==val[u]) {splay(u);return false;}
add(v>val[u]?rc[u]:lc[u],u,v);
splay(v>val[u]?rc[u]:lc[u]);
return true;
}
inline int front(int u){
int k=lc[u];
if(k==0) return -1e7;
while(rc[k]) k=rc[k];
return val[k];
}
inline int back(int u)
{
int k=rc[u];
if(k==0) return -1e7;
while(lc[k]) k=lc[k];
return val[k];
}
int main(){
n=read();
int ans=0,x;
for(int i=1;i<=n;i++)
{
x=read();
if(i==1)
{
ans+=x;
add(root,0,x);
}
else
{
if(!insert(x)) continue;
ans+=(min(abs(x-front(root)),abs(x-back(root))));
}
}
cout<<ans<<endl;
return 0;
}
treap写法
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') {f=-1;c=getchar();}
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
int n,root=1,tot,ans;
int lc[50105],rc[50105],data[50105],val[50105];
const int inf =1e9+7;
inline int add(int va)
{
val[++tot]=va;
data[tot]=rand();
return tot;
}
inline void build()
{
add(-inf);
add(inf);
rc[1]=2;
}
inline void zig(int &p)
{
int q=lc[p];
lc[p]=rc[q],rc[q]=p,p=q;
}
inline void zag(int &p)
{
int q=rc[p];
rc[p]=lc[q],lc[q]=p,p=q;
}
inline void insert(int &p,int va)
{
if(p==0)
{
p=add(va);
return ;
}
if(va==val[p]) return ;
if(va<val[p])
{
insert(lc[p],va);
if(data[lc[p]]>data[p]) zig(p);
}
else
{
insert(rc[p],va);
if(data[rc[p]]>data[p]) zag(p);
}
}
inline int pre(int va)
{
int cur=1,p=root;
while(p)
{
if(val[p]==va) return va;
if(val[p]<va&&val[p]>val[cur]) cur=p;
p=val[p]>va?lc[p]:rc[p];
}
return val[cur];
}
inline int nxt(int va)
{
int cur=2,p=root;
while(p)
{
if(val[p]==va)return va;
if(val[p]>va&&val[p]<val[cur]) cur=p;
p=val[p]>va?lc[p]:rc[p];
}
return val[cur];
}
int main(){
srand(time(0));
int ans=0,x;
n=read();
build();
for(int i=1;i<=n;i++)
{
x=read();
if(i==1)
{
ans+=x;
}
else
{
int a=pre(x),b=nxt(x);
if(a==-inf&&b!=inf) ans+=b-x;
if(a!=-inf&&b==inf) ans+=x-a;
if(a!=-inf&&b!=inf) ans+=min((x-a),(b-x));
}
insert(root,x);
}
cout<<ans<<endl;
return 0;
}