题解 P2234 【[HNOI2002]营业额统计】
P2234 [HNOI2002]营业额统计
题目大意:
求:
\[\sum _{i=1} ^{n} \min _{j=1} ^{i-1}\{|a[\,i\,]-a[\,j\,]|\}
\]
solution:
观察柿子就是求 \(a[\,i\,]\) 的前驱后继。做差取个最小值累加进答案中即可。用 \(\text{Splay}\) 维护。
细节处理:
绝对值还是用 \(\text{fabs}\) 吧[捂脸]。
代码
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL INF=9223372036854775807,FINF=-INF;
const int N=32800;
int n,rt,tot;
LL a[N],ans;
LL val[N];int siz[N],fa[N],son[N][2],cnt[N];
inline void pushup(int u){
siz[u]=siz[son[u][0]]+siz[son[u][1]]+cnt[u];
}
inline void rotate(int x){
int y=fa[x],z=fa[y];
int k=son[y][1]==x;
son[z][son[z][1]==y]=x,fa[x]=z;
son[y][k]=son[x][k^1],fa[son[x][k^1]]=y;
son[x][k^1]=y,fa[y]=x;
pushup(y),pushup(x);
}
inline void splay(int x,int goal){
while(fa[x]!=goal){
int y=fa[x],z=fa[y];
if(z!=goal)
((son[y][1]==x)^(son[z][1]==y))?rotate(x):rotate(y);
rotate(x);
}
if(!goal) rt=x;
}
inline void find(int v){
int u=rt;
if(!u) return ;
while(son[u][v>val[u]]&&v!=val[u])
u=son[u][v>val[u]];
splay(u,0);
}
inline void insert(LL v){
int u=rt,f=0;
while(u&&val[u]!=v)
f=u,u=son[u][v>val[u]];
if(u) cnt[u]++;
else{
u=++tot;
if(f) son[f][v>val[f]]=u;
val[u]=v,fa[u]=f,
siz[u]=1,cnt[u]=1;
}
splay(u,0);
}
inline int Nxt(int v,bool f){
find(v);
int u=rt;
if(val[u]>=v&&f) return u;
if(val[u]<=v&&!f) return u;
u=son[u][f];
while(son[u][f^1])
u=son[u][f^1];
return u;
}
int main(){
insert(INF),insert(FINF);
scanf("%d%lld",&n,&a[1]);
insert(a[1]),ans+=a[1];
for(int i=2;i<=n;i++){
scanf("%lld",&a[i]);
ans+=min(fabs(a[i]-val[Nxt(a[i],0)]),fabs(val[Nxt(a[i],1)]-a[i]));
insert(a[i]);
}
printf("%lld",ans);
return 0;
}

浙公网安备 33010602011771号