[HNOI2002]营业额统计
题目大意:给出含N个数的序列,定义第i个数的权为其与前i-1个数的最小差值,求权和
平衡树模板题,但是此题有相当巧妙的线性表解法。
对N个数排序并建立双向链表,依照从第N个数开始,检查其在链表中的前驱与后继,计入权后删去,最后输出即为权和。
//营业额统计 线性表
#include<cstdio>
#define min(a,b) a<b?a:b
#define N 1000000
int n,input[N],ins[N],num[N],id[N],last[N],next[N];
int fabs(int i){return i>0?i:-i;}
int Quick(int i,int j){
int k=ins[i],t=id[i];
while(i<j){
while(i<j && ins[j]>=k) j--;
ins[i]=ins[j];id[i]=id[j];
while(i<j && ins[i]<=k) i++;
ins[j]=ins[i];id[j]=id[i];
}
ins[i]=k;id[i]=t;
return i;
}
void Sort(int i,int j){
if(i<j){
int k=Quick(i,j);
Sort(i,k-1);
Sort(k+1,j);
}
}
int main(){
long res;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&ins[i]);
input[i]=ins[i];
id[i]=i;
}
Sort(1,n);
for(int i=1;i<=n;i++){
num[id[i]]=i;
last[id[i]]=id[i-1];
next[id[i]]=id[i+1];
}
res=0;
input[0]=input[n+1]=2147483647;
for(int i=n;i>1;i--){
res+=min(fabs(input[i]-input[last[i]]),fabs(input[i]-input[next[i]]));
next[last[i]]=next[i];
last[next[i]]=last[i];
}
res+=input[1];
printf("%ld\n",res);
return 0;
}