mice

Description

有一天Masha回到家,发现有n只老鼠在它公寓的走廊上,她大声呼叫,所以老鼠们都跑进了走廊的
洞中。
这个走廊可以用一个数轴来表示,上面有n只老鼠和m个老鼠洞。第i只老鼠有一个坐标x i ,第j个洞有
一个坐标p j 和容量c j 。容量表示最多能容纳的老鼠数量。
找 到 让 老 鼠 们 全 部 都 进 洞 的 方 式,使 得 所 有 老 鼠 运 动 距 离 总 和 最 小。 老 鼠i进 入 洞j的 运 动 距 离
为|x i − p j |
无解输出-1。

solution

正解:调整贪心
还是老套路,在能使得答案更小时,我们就直接决策,并加入后悔操作,在这个题目中,我们将老鼠和老鼠洞排个序,然后扫描,开两个堆:老鼠堆和老鼠洞堆.
如果碰到老鼠,我们直接把他丢进最近的一个洞中,计算答案 \(x[i]-p[j]\) 并且将 \(x[i]+x[i]-p[j]\) 丢入老鼠堆中.
如果碰到老鼠洞,我们一直把前面能够使得答案更小的老鼠都加入到这个洞中,并且把后悔操作丢入老鼠洞的堆中.
巧妙的是:处理限制的方法:我们在用掉一次老鼠洞后,我们判断是否有剩余容量,如果有,我们再加入一次堆即可

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#define RG register
using namespace std;
typedef long long ll;
const int N=2000005;
const ll inf=2e15;
inline int gi(){
    RG int str=0;RG char ch=getchar();bool h=0;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=getchar();
    if(ch=='-')h=1,ch=getchar();
    while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
    return h?-str:str;
}

#define x first
#define y second

int n,m;
struct node{
    ll x;int y;
    node(){}
    node(ll _x,int _y){x=_x;y=_y;}
    bool operator <(const node &pr)const{return x<pr.x;}
};
pair<ll,int>p[N];
priority_queue<ll>qm;
priority_queue<node>qd;
void work()
{
    int tot=0,x,y,j;ll sum=0;
    cin>>n>>m;
    for(int i=1;i<=n;i++)p[++tot]=make_pair(gi(),-1);
    for(int i=1;i<=m;i++){
        x=gi();y=gi();sum+=y;
        p[++tot]=make_pair(x,y);
    }
    if(sum<n){puts("-1");return ;}
    sort(p+1,p+tot+1);
    ll w,ans=0;
    for(RG int i=1;i<=tot;i++){
        if(p[i].y==-1){
            w=inf;
            if(!qd.empty()){
                w=p[i].x-qd.top().x;j=qd.top().y;qd.pop();
                if(p[j].y)p[j].y--,qd.push(node(p[j].x,j));
            }
            ans+=w;
            qm.push(p[i].x+w);
        }
        else{
            while(!qm.empty() && p[i].y && p[i].x-qm.top()<0){
                w=p[i].x-qm.top();
                p[i].y--;qm.pop();
                qd.push(node(p[i].x+w,0));
                ans+=w;
            }
            if(p[i].y)p[i].y--,qd.push(node(p[i].x,i));
        }
    }
    cout<<ans<<endl;
}

int main()
{
    work();
    return 0;
}

转载于:https://www.cnblogs.com/Hxymmm/p/7795738.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值