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;
}

posted @ 2017-11-06 23:01  Hxymmm  阅读(613)  评论(0编辑  收藏  举报