【bzoj 1588】营业额统计

传送门~

解题思路

按大小顺序建链表,然后按从后向前的顺序依次删除每个元素并统计答案。
稳稳水过,需要一些奇技淫巧。
代码:

#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
using namespace std;
int a[40005],xi[40005],sh[40005];
int s[40005],wi[40005],di[40005];
int n,ans,inf=2147483640;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&s[i]);
        a[i]=s[i];
    }
    sort(a+1,a+n+1);
    int top=unique(a+1,a+n+1)-a-1;
    for(int i=1;i<=n;i++) {
        wi[i]=lower_bound(a+1,a+top+1,s[i])-a;
        di[wi[i]]++;
    }
    xi[0]=1;sh[top+1]=top;
    for(int i=1;i<=top;i++){
        sh[i]=i-1;
        xi[i]=i+1;  
    }
    for(int i=n;i>=2;i--){
        int rc=inf,w=wi[i];
        if(di[w]>1) rc=0;
        else{
            if(sh[w]!=0) rc=min(rc,abs(a[w]-a[sh[w]]));
            if(xi[w]!=top+1) rc=min(rc,abs(a[w]-a[xi[w]]));
        }
        ans+=rc;di[w]--;
        if(!di[w]) {xi[sh[w]]=xi[w];sh[xi[w]]=sh[w];}
    }
    printf("%d",ans+s[1]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值