第九届图灵杯-金牌厨师-(二分+思维)

K

题意:
就是给你n个辣度的菜,分别是1~n,然后和m个人,每个人可以接受的辣度的菜为l,r。然后有一个满意程度定义为,选出k个同学,和能让这些同学都接受的辣度的菜的个数为x,则满足度为min(k,x)。现在问你最大的满意度是多少。

思考:
看到这题,还取了min,感觉就是二分题。但是刚开始写了个假做法,直接按每个辣度被喜欢的程度sum排序,从1到n取min(i,sum[i]),这是不对的,因为当前的值不能代表是哪些同学喜欢,所以不可以。那么就只能二分了,但是check该怎么写呢,如果每次还是l,r这段区间的权值加1最后也是没法判断。其实可以从va[i].fi+mid-1到va[i].se这段区间加加,因为这样肯定能满足从这个点开始能往前喜欢mid个辣度。所以最后就可以直接判断当前点sum[i]是否大于mid即可。

代码:

int T,n,m,k;
PII va[N];
int sum[N];

bool check(int mid)
{
	for(int i=0;i<=n;i++) sum[i] = 0;
	for(int i=1;i<=m;i++)
	{
		int len = va[i].se-va[i].fi+1;
		if(len>=mid) //ÿ¸öÈ˶¼¿ÉÒÔÔÚÏÂÃæµÄÒ»¶ÎÇø¼äÄÚÍùÇ°ÕÒmid¸öÀ±¶È
		{ //Èç¹ûÓÃsum[va[i].fi]++,ÔòÏÂÃæÅжϵÄʱºò²»Ò»¶¨ÄÜÂú×ãËûÄÜÑ¡mid¸öÀ±¶È 
			sum[va[i].fi+mid-1]++;
			sum[va[i].se+1]--;
		}
	}
	for(int i=1;i<=n;i++)
	{
		sum[i] += sum[i-1];
		if(sum[i]>=mid) return true;
	}
	return false;
}

signed main()
{
	IOS;
	cin>>n>>m;
	for(int i=1;i<=m;i++) cin>>va[i].fi>>va[i].se;
	int l = 1,r = min(n,m);
	while(l<r)
	{
		int mid = l+r+1>>1;
		if(check(mid)) l = mid;
		else r = mid-1;
	}
	cout<<l<<"\n";
	return 0;
}

总结:
多多积累经验,换种思维方式和判断方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值