Codeforces Round #657 (Div. 2)补题D New Passenger Trams

Codeforces Round #657 (Div. 2)补题D New Passenger Trams_第1张图片

Codeforces Round #657 (Div. 2)补题D New Passenger Trams_第2张图片

Codeforces Round #657 (Div. 2)补题D New Passenger Trams_第3张图片

题意:某个星球的一天有h小时,一小时有m分钟,现在有两种车要开,红色的每半小时开一次,每次要准备k分钟再开。蓝色的车有固定的时刻表,且没有准备时间,但是它与红色的车的时间重合了就会被取消掉(端点重合不取消),问你第一辆红色车的开始时间是多少才能使取消掉最小的蓝色车的数量最小。

分析:小时数h肯定使没用的,因为一辆蓝车在h1发车和h2发车不会对我们产生任何影响。同理,这辆蓝车在m1发车(m1

那么题目就可以简化成已经模了m/2的n个数,要找出一段k长度的区间,包含最少这些数。(端点不算)

因此立马想到尺取法。遍历这n个数。这里有一个trick,将这些数全部+m/2放入数组,然后再尺取。这样可以防止尺取死循环(一直找不到大于等于k的时间段),实际上这种情况意味着全包含。比如m是100,k是50,有9辆车都是49发车,一辆车是2发车。那么计算的时候就是有99发车,但是从49到99都可以走,中间只有一个52.这就说明只有一个2在里面。相反,如果不用这个trick,只有2和49,无论如何也找不到合格的解能大于等于50(52-49=3,49-2=47),不符合实际情况。虽然这个trick的物理意义我还不是很懂,希望大佬教教我。

代码:

#include
using namespace std;
struct che
{
	int pos;
	int t;
}shi[200005];
int ji[100005];
int cmp1(che x1,che x2)
{
	return x1.t=k)
		{
			l++;
			if (l>=n) break;
		}
		tmpans=r-l;//这种方案会误几班车 
		if (ans>tmpans)
		{
			ans=tmpans;
			jipos1=l;
			jipos2=r;
		}
		if (l>=n) break;
	} 
	tmp=0;
	for (int i=jipos1;i

这题花了好久,第一是尺取法不会了。。。写了一个假的,第二是想这个trick之前一直死循环。

你可能感兴趣的:(算法训练)