ZCMU--5087: 宠物

Description

现在有一个宠物收养所,提供两种服务,可以将被主人遗弃的宠物放到收养所里,如果有人希望可以领养宠物的话,他也可以来收养所领养被别人遗弃的宠物。

       为了方便领养者领养宠物,所以这里给每个宠物和领养者进行了评估,记为特征值(当然任何两只宠物的特征值都是不同的,任何两个人的特征值也是不同的),那么对于特征值越相近的宠物和领养者,他们更容易相处,也会更加开心。

       收养所总是会有两种情况发生:宠物过多或者领养者过多。

1.       当宠物过多时,若有一个领养者到来,这个领养者的特征值为x,那么他将会领养现在收养所的所有宠物中特征值最接近x的一只宠物,如果有两只宠物满足 x-a = b-x (a<x,b>x),那么这个领养者会领养特征值为a的宠物

2.       当领养者过多时,那么领养者会在收养所中登记,当来到一只宠物时,设它的特征值为x,那么会领养它的领养者就是特征值最接近x的人,如果有两个领养者满足x-a = b-x (a<x,b>x),那么这只宠物会被特征值为a的领养者领养。

当一个特征值为x的领养者领养了一只特征值为y的宠物以后,他的不开心程度为abs(x-y)。

现在告诉你一段时间中,领养者和被遗弃的宠物来到收养所的顺序,希望你计算所有领养了宠物的领养者的不开心程度的总和,当然在这段时间开始前,收养所里没有任何宠物也没有登记任何领养者。

Input

数据第一个行包含一个正整数n,表示这段时间中来到收养所的宠物和领养者的总数。

接下来n行表示按顺序到来的领养者或者宠物的情况。每行两个整数 x,y ,其中 x=0 表示这次到来的是一只宠物,x=1表示这次到来的是一个领养者,y表示的是这次来到的宠物或领养者的特征值(保证同一时间内收养所中不会有超过10000只宠物,也不会登记超过10000个领养者)

Output

输出包含一个整数表示这段时间中所有收养了宠物的领养者的不满意程度的总和,因为这个答案比较大,所以对998244353 取模。

Sample Input

5
0  2
0  4
1  3
1  2
1  5

Sample Output

3

HINT

第一个领养者会领养特征值为2的宠物

第二个领养者会领养特征值为4的宠物

第三个领养者没有宠物可以领养

总的不满意程度为abs(3-2)+abs(2-4)=3

 40%的数据保证: 1≤n≤800

100%的数据保证:1≤n≤80000,a<=2^31-1

解析:利用vector二分插入,二分查找然后按题意比较即可,注意下边界😢

开两个vector数组a,b,一个宠物一个领养者

1.如果输入是宠物时,先看b中有没有人,没有人的话就偷偷用lower_bound( begin,end,num)👀,查找第一个大于或等于num的数字,找到返回该数字的地址,实现宠物插入a数组

2.有领养者的话二分查找第一个大于等于v的位置z,因为前后是b[z-1]和b[z],避免z-1越界,分2种情况,如果是第一个位置,那肯定选他,其他情况需要比较b[z-1]和b[z]哪个更接近,选了之后再在数组中删除即可。

3.输入是人的话,相反同理

#include <stdio.h>
#include <stdlib.h>
#include <vector>
const int mod=998244353;
using namespace std;
vector<int> a,b;
int main()
{	
	int n,y,s=0,z,m,k,v;
	scanf("%d",&n);
	while(n--){
		scanf("%d%d",&k,&v);//k来判断是宠物还是人,v是特征值 
		if(k==0){
			if(b.size()>0){//如果有人 
				z=0;y=b.size()-1;
				while(z<y){
					m=(z+y)>>1;
					if(b[m]>=v) y=m;
					else z=m+1;
				}
				//a[z]是第一个大于等于v的位置 
				if(z==0) s=(s+abs(v-b[z]))%mod,b.erase(b.begin());//第一个位置,肯定是他无疑 
				else if(abs(v-b[z-1])<=abs(b[z]-v)) s=(s+abs(v-b[z-1]))%mod,b.erase(b.begin()+z-1);//前面一个更接近 
				else if(abs(v-b[z-1])>abs(b[z]-v)) s=(s+abs(v-b[z]))%mod,b.erase(b.begin()+z);//后面更接近 
			}else a.insert(lower_bound(a.begin(),a.end(),v),v);//没人,存进宠物 
		}else{
			//跟上面反一下,同理 
			if(a.size()>0){	//如果有宠物 
				z=0;y=a.size()-1;
				while(z<y){
					m=(z+y)>>1;
					if(a[m]>=v) y=m;
					else z=m+1;
				}
				if(z==0) s=(s+abs(v-a[z]))%mod,a.erase(a.begin());
				else if(abs(v-a[z-1])<=abs(a[z]-v)) s=(s+abs(v-a[z-1]))%mod,a.erase(a.begin()+z-1);
				else if(abs(v-a[z-1])>abs(a[z]-v)) s=(s+abs(v-a[z]))%mod,a.erase(a.begin()+z);
			}else b.insert(lower_bound(b.begin(),b.end(),v),v);//没宠物存人 
		}
	}
	printf("%d\n",s);
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值