luogu4264 [USACO18FEB]Teleportation S

http://www.elijahqi.win/2018/03/06/luogu4264/
题目描述

One of the farming chores Farmer John dislikes the most is hauling around lots of cow manure. In order to streamline this process, he comes up with a brilliant invention: the manure teleporter! Instead of hauling manure between two points in a cart behind his tractor, he can use the manure teleporter to instantly transport manure from one location to another. Farmer John’s farm is built along a single long straight road, so any location on his farm can be described simply using its position along this road (effectively a point on the number line). A teleporter is described by two numbers

x
x and

y
y , where manure brought to location

x
x can be instantly transported to location

y
y .

Farmer John decides to build a teleporter with the first endpoint located at

x=0
x=0 ; your task is to help him determine the best choice for the other endpoint

y
y . In particular, there are

N
N piles of manure on his farm (

1 \leq N \leq 100,000
1≤N≤100,000 ). The

i
i th pile needs to moved from position

a_i
ai​ to position

b_i
bi​ , and Farmer John transports each pile separately from the others. If we let

d_i
di​ denote the amount of distance FJ drives with manure in his tractor hauling the

i
i th pile, then it is possible that

d_i = |a_i-b_i|
di​=∣ai​−bi​∣ if he hauls the

i
i th pile directly with the tractor, or that

d_i
di​ could potentially be less if he uses the teleporter (e.g., by hauling with his tractor from

a_i
ai​ to

x
x , then from

y
y to

b_i
bi​ ).

Please help FJ determine the minimum possible sum of the

d_i
di​ ‘s he can achieve by building the other endpoint

y
y of the teleporter in a carefully-chosen optimal position. The same position

y
y is used during transport of every pile.

输入输出格式

输入格式:
The first line of input contains

N
N . In the

N
N lines that follow, the

i
i th line contains

a_i
ai​ and

b_i
bi​ , each an integer in the range

-10^8 \ldots 10^8
−108…108 . These values are not necessarily all distinct.

输出格式:
Print a single number giving the minimum sum of

d_i
di​ ‘s FJ can achieve. Note that this number might be too large to fit into a standard 32-bit integer, so you may need to use large integer data types like a “long long” in C/C++. Also you may want to consider whether the answer is necessarily an integer or not…

输入输出样例

输入样例#1: 复制

3
-5 -7
-3 10
-2 7
输出样例#1: 复制

10
说明

In this example, by setting

y = 8
y=8 FJ can achieve

d_1 = 2
d1​=2 ,

d_2 = 5
d2​=5 , and

d_3 = 3
d3​=3 . Note that any value of

y
y in the range

[7,10]
[7,10] would also yield an optimal solution.

Problem credits: Brian Dean

银里最神的题了?我没有ak进到au 实在太菜

首先写出式子min(|a|+|y-b|,|a-b|) 那么可以分类讨论一下 把这个式子写出一次函数的形式

观察到 它应该会存在斜率为+1或者-1的向下凸起 那么我们不妨假设首先我每个的代价都是 a-b 然后我去观察这个图像 来写出我到底是什么时候能够使得减小量最大 那么我们不妨把减小量倒过来 变成向上凸起的山峰 现在相当于求所有山峰的最大值即可 怎么求 我针对山峰的左端点排序 再针对山顶排序 做的时候根据已经添加的山峰的最右端维护一个小根堆 然后弹出为了计算山峰和山峰之间的答案我们怎么搞呢 就是首先删除到一半就停止了的山峰 然后对下坡和上坡的差值进行计算 然后添加上中间进入的山峰 注意过了一个山顶之后需要将上坡和下坡进行一个交换

#include<queue>
#include<vector>
#include<cstdio>
#include<algorithm>
#define N 110000
#define ll long long
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();}
    while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
    return x*f;
}
inline int abs(int x){return x<0?-x:x;}
struct node{
    int l,r,top;
    inline friend bool operator <(const node &a,const node &b){
        return a.r>b.r;
    }
}data[N],data1[N];
priority_queue<node,vector<node> >q;
int n,cnt,up,down;ll ans=0,mx1,mx;
inline bool cmp1(const node &a,const node &b){return a.l<b.l;}
inline bool cmp2(const node &a,const node &b){return a.top<b.top;}
int main(){
//  freopen("teleport.in","r",stdin);
//  freopen("teleport.out","w",stdout);
    n=read();ans=0;
    for (int i=1;i<=n;++i){
        int a=read(),b=read(),l,r;node tmp;tmp.top=b;
        ans+=abs(a-b);if (abs(a-b)<=abs(a)) continue;
        if (a>=0){
            if (a>b){l=b-b,r=2*b;if (l>r) swap(l,r);tmp.l=l;tmp.r=r;}
            if (a<b){l=a<<1;r=2*b-2*a;if (l>r) swap(l,r);tmp.l=l;tmp.r=r;}
            data1[++cnt]=data[cnt]=tmp;continue;
        }if (a>b){l=a<<1;r=2*b-2*a;if (l>r) swap(l,r);tmp.l=l;tmp.r=r;}
        if (a<b){l=b-b,r=2*b;if (l>r) swap(l,r);tmp.l=l;tmp.r=r;}
        data1[++cnt]=data[cnt]=tmp;
    }sort(data+1,data+cnt+1,cmp1);sort(data1+1,data1+cnt+1,cmp2);
    int now=1;
    for (int i=1;i<=cnt;++i){
        while(!q.empty()&&q.top().r<data1[i].top) {
            mx1-=q.top().r-data1[i-1].top,q.pop(),--down;
        }mx1+=(ll)(up-down)*(data1[i].top-data1[i-1].top);
        while(data[now].l<=data1[i].top&&now<=cnt) {
            q.push(data[now]),++up,mx1+=data1[i].top-data[now].l;++now;
        }
        mx=max(mx,mx1);--up;++down;
    }
    printf("%lld\n",ans-mx);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值