第九届图灵杯-金牌厨师

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

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

上一篇:Apprentissage du français partie 3


下一篇:数据结构---06---数组---20205106009---郭睿玥