cf#310-D. Case of Fugitive-贪心

70 篇文章 0 订阅

给你n个岛屿的左右端点(l.r)(此题岛屿不是点,是一个区间)

给你m个桥

题目要求桥大于等于两个岛屿之间的 min距离,且小于等于其max距离,min=bridge(i+1).L-bridge(i).r。  max=bridge(i+1).r-bridge(i).l;

思路: 


先对桥排序

再对岛屿排序,应该先对max距离从小到大排序,max相同则对min从小到大排序 


关键就是 要 选桥的时候,优先考虑 max值最小的岛屿, 对于他们来说,选择一条 最接近min值的桥一定是最优的

对于当前这个max最小的岛屿,用他的min在 桥里面二分找到第一个恰好大于等于min的len,

如果len>max|| 找不到满足条件的桥len,那么此两岛屿肯定无解(因为之后的桥的len肯定大于当前的len,也就是不可能出现len<=max)

如果len<=max,那么必为最优解,因为不可能出现 此后的岛屿对只能选当前的桥才合法(比较难证明...233)


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;

#define inf 1223372036854775807
struct node
{
	__int64 l,r;
};
node tm[200005];
struct DISTANCE
{
	__int64 	mi,mx;
	__int64 num;
	__int64 bb;
};
__int64 cmp(DISTANCE a,DISTANCE b)
{
 
		 if (a.mx!=b.mx)
		 return a.mx<b.mx;
		 else
			 return a.mi<b.mi;
}
__int64 final_cmp(DISTANCE a,DISTANCE b)
{
	return a.num<b.num;
}
struct BRI
{
	__int64 len,num;
	bool operator<( const BRI& b)   const
	{
		if (len!=b.len)
		return len<b.len;
		else
	 		return num<b.num;

	}
		bool operator==( const BRI& b)   const
	{
		return len==b.len&&num==b.num;

	}
};

DISTANCE dis[200005];

set <BRI> bri;
set <BRI> ::iterator it;
int main()
{
	__int64 n,m;
	__int64 i,j;
	scanf("%I64d%I64d",&n,&m);
	for (i=1;i<=n;i++)
	{
		scanf("%I64d%I64d",&tm[i].l,&tm[i].r);
	}

	for (i=1;i<=n-1;i++)///dis[i]---i??i+1????????????Χ
	{
		dis[i].mi=tm[i+1].l-tm[i].r;
		dis[i].mx=tm[i+1].r-tm[i].l;
		dis[i].num=i;
	}
	sort(dis+1,dis+1+n-1,cmp);
	__int64 tt;
	for (i=1;i<=m;i++)
	{
		scanf("%I64d",&tt);
		BRI tp;
		tp.len=tt;
		tp.num=i;
		bri.insert(tp);
	}

	for (i=1;i<=n-1;i++)
	{
		BRI tp;
		tp.len=dis[i].mi;
		tp.num=0; 
		it=	bri.lower_bound(tp); 

	if ((*it).len >dis[i].mx||it==bri.end())
		break;
	else
		{
			dis[i].bb=it->num;
			BRI del;
			del.len=it->len;
			del.num=it->num;
			bri.erase(del);
		}


	}

	if (i==n)
	{

		printf("Yes\n");
		sort(dis+1,dis+n,final_cmp);

		for (i=1;i<=n-1;i++)
		{
			if (i!=1) printf(" ");
			printf("%I64d",dis[i].bb);
		}
		printf("\n");
	}
	else
	{
		printf("No\n");


	}
	return 0;

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值