P2286 [HNOI2004] 宠物收养场 题解

题目链接

用set可以比较方便的实现这道题。

根据题意,我们维护两个set,一个主人s2一个宠物s1,一开始先分别插入一个极大值一个极小值,如果输入的是宠物,价值为b,就在s2中找到两个数t1,t2,分别是比当前b小的数的最大值,比当前b大的最小值。价值差就是

max(b-t1,t2-b);

然后根据这个来加入更大一点的,如果已经没有可以找的了就把当前要找的存着以后用。

对于怎么找两个值,我们用lower_bound来解决,it是用Lower bound找大于等于b的第一个指针,那么it的前一个 数就是小于b的最大值。

#include<bits/stdc++.h>
using namespace std;
const int N=80005;
const int INF=1e9+10;
const int mod=1000005;
int n,ans;
set<int> s1,s2;
set<int>:: iterator it;
int main()
{
	scanf("%d",&n);
	s1.insert(-INF); s1.insert(INF);
	s2.insert(-INF); s2.insert(INF);
	for(int i=1,a,b;i<=n;i++)

	{
		scanf("%d%d",&a,&b);
		if(a==0)
		{
			if(s2.size()==2)
			{
				s1.insert(b);
				continue;
			}
			it=s2.lower_bound(b);
			int t2=*it,t1=*(--it),x1,x2;
			x1=b-t1; x2=t2-b;
			if(x1<=x2)
			{
				ans=(ans+x1)%mod;
				s2.erase(t1);
			}
			else
			{
				ans=(ans+x2)%mod;
				s2.erase(t2);
			}	
		}
		else
		{
			if(s1.size()==2)
			{
				s2.insert(b);
				continue;
			}
			it=s1.lower_bound(b);
			int t2=*it,t1=*(--it),x1,x2;
			x1=b-t1; x2=t2-b;
			if(x1<=x2)
			{
				ans=(ans+x1)%mod;
				s1.erase(t1);
			}
			else
			{
				ans=(ans+x2)%mod;
				s1.erase(t2);
			}
		}
	}
	printf("%d\n",ans);
	return 0;
}

然而这样会全WA。。。

因为当我们找最大值和最小值时,当有找不到的时,我们赋的极值就会影响答案,然后我就打了个看上去似乎挺冗杂的特判

	if(t1==-INF)
	{
		ans=(ans+x2)%mod;
		s2.erase(t2);
	}
	else if(t2==INF)
	{
		ans=(ans+x1)%mod;
		s2.erase(t1);
	}
	else if(x1<=x2)
	{
		ans=(ans+x1)%mod;
		s2.erase(t1);
	}
	else if(x1>x2)
	{
		ans=(ans+x2)%mod;
		s2.erase(t2);
	}	

这样就OK啦

最后上个完整的码

#include<bits/stdc++.h>
using namespace std;
const int N=80005;
const int INF=1e9+10;
const int mod=1000000;
int n,ans;
set<int> s1;
set<int> s2;
set<int>:: iterator it;
int main()
{
	scanf("%d",&n);
	s1.insert(-INF); s1.insert(INF);
	s2.insert(-INF); s2.insert(INF);
	for(int i=1,a,b;i<=n;i++)
	{
		scanf("%d%d",&a,&b);
		if(a==0)
		{
			if(s2.size()==2)
			{
				s1.insert(b);
				continue;
			}
			it=s2.lower_bound(b);
			int t2=*it,t1=*(--it),x1,x2;
			if(t1==-INF&&t2==INF) continue;
			x1=b-t1; x2=t2-b;
			if(t1==-INF)
			{
				ans=(ans+x2)%mod;
				s2.erase(t2);
			}
			else if(t2==INF)
			{
				ans=(ans+x1)%mod;
				s2.erase(t1);
			}
			else if(x1<=x2)
			{
				ans=(ans+x1)%mod;
				s2.erase(t1);
			}
			else if(x1>x2)
			{
				ans=(ans+x2)%mod;
				s2.erase(t2);
			}	
		}
		else
		{
			if(s1.size()==2)
			{
				s2.insert(b);
				continue;
			}
			it=s1.lower_bound(b);
			int t2=*it,t1=*(--it),x1,x2;
			if(t1==-INF&&t2==INF) continue;
			x1=b-t1; x2=t2-b;
			if(t1==-INF)
			{
				ans=(ans+x2)%mod;
				s1.erase(t2);
			}
			else if(t2==INF)
			{
				ans=(ans+x1)%mod;
				s1.erase(t1);
			}
			else if(x1<=x2)
			{
				ans=(ans+x1)%mod;
				s1.erase(t1);
			}
			else if(x1>x2)
			{
				ans=(ans+x2)%mod;
				s1.erase(t2);
			}
		}
	}
	printf("%d\n",ans%mod);
	return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值