Codeforces Round #477 (rated, Div. 2, based on VK Cup 2018 Round 3) ABC

A. Mind the Gap

传送门:http://codeforces.com/contest/967/problem/A


题目大意:

  给定n个飞机着陆时间点,以及时间差s,并且起飞和着陆需要1分钟,即时间差为s+1。现在要插入一个飞机起飞的时间点,使得这n+1个时间点仍然保持两两之间相差s+1分钟。


AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define P pair
#define ll long long
#define INF 100000000
#define M 1e9+7
#define MAX 500010
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
using namespace std;

int n, t, ansh, anss;
int h[110], s[110];

int main()
{
	cin >> n >> t;
	for (int i = 0; i < n; i++)
		cin >> h[i] >> s[i];

	ansh = 0; anss = 0;
	for (int i = 0; i < n; i++) {
		if ((h[i] - ansh) * 60 + s[i] - anss >= t + 1)
			break;
		anss = s[i] + t + 1;
		ansh = h[i];
		if (anss >= 60) {
			ansh += anss / 60;
			anss -= (anss / 60) * 60;
		}
	}
	cout << ansh << ' ' << anss << endl;
	return 0;
}


B. Watering System

传送门:http://codeforces.com/contest/967/problem/B


题目大意:

  一个水管有n个洞,洞的大小分别为s1,s2……sn。当倒入A升的水时,每个洞会流出(si*A)/S升的水,其中S为洞的大小之和。问最少封掉多少洞能够在第一个洞中流出至少B升的水。(显然第一个洞是不封的)


思路:

  第一个洞流出的水是(s1*A)/S,其中只有S会发生变化,那么只要排个序从最大的开始封就好了。


AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define P pair
#define ll long long
#define INF 100000000
#define M 1e9+7
#define MAX 500010
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
using namespace std;

int n;
int a, b;
int s[100010];

bool cmp(int a, int b)
{
	return a > b;
}

int main()
{
	cin >> n >> a >> b;
	int tot = 0;
	for (int i = 0; i < n; i++) {
		cin >> s[i];
		tot += s[i];
	}
	int first_h = s[0];
	sort(s, s + n, cmp);

	int left = first_h*a / tot;
	int cnt = 0;
	bool judge = false;
	while (left < b) {
		if (!judge) {
			if (s[cnt] == first_h) {
				cnt++;
				judge = true;
				continue;
			}
		}
		tot -= s[cnt++];
		left = first_h*a / tot;
	}
	if (judge)
		cnt--;
	cout << cnt << endl;
	return 0;
}


C. Stairs and Elevators

传送门:http://codeforces.com/contest/967/problem/C


题目大意:

  一幢n*m的大楼,有楼梯和电梯,分别分布在cl和ce条列上。楼梯每走一楼花费1个时间单元,电梯每走v楼花费1个时间单元,当然在同一个楼层里左右走一格也花费1个时间单元。问从(x1,y1)到(x2,y2)最快需要花费几个时间单元。


思路:

  对于不在同一层的,楼梯和电梯分别都算一次然后求最小值。竖向的距离直接就是abs(y2-y1);横着的如果楼梯/电梯在x1和x2之间,则距离是abs(x2-x1),否则选取离x1最近的或离x2最近的楼梯/电梯,假设距离为d,则距离是abs(x2-x1)+2*d。

  对于在同一层的,根本不用找楼梯或者电梯,直接走过去就可以了。


AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define P pair
#define ll long long
#define INF 1e9
#define M 1e9+7
#define MAX 500010
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
using namespace std;

int n, m, c1, c2, v, q;
int stair[100010], elevator[100010];

int main()
{
	cin >> n >> m >> c1 >> c2 >> v;
	for (int i = 0; i < c1; i++)
		scanf("%d", &stair[i]);
	for (int i = 0; i < c2; i++)
		scanf("%d", &elevator[i]);

	cin >> q;
	int x1, y1, x2, y2;
	int ans1, ans2;
	while (q--) {
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		int temp = min(x1, x2);
		x2 = max(x1, x2); x1 = temp;
		temp = min(y1, y2);
		y2 = max(y1, y2); y1 = temp;

		if (x1 == x2) {
			cout << y2 - y1 << endl;
			continue;
		}
		ans1 = 0; ans2 = 0;

		int pos = lower_bound(stair, stair + c1, y1) - stair;
		if (pos != c1&&stair[pos] <= y2)
			ans1 += y2 - y1;
		else {
			int a1 = INF, a2 = INF;
			if (pos != 0)
				a1 = y1 - stair[pos - 1];
			pos = lower_bound(stair, stair + c1, y2) - stair;
			if (pos != c1)
				a2 = stair[pos] - y2;
			ans1 += y2 - y1 + 2 * min(a1, a2);
		}
		ans1 += x2 - x1;

		pos = lower_bound(elevator, elevator + c2, y1) - elevator;
		if (pos != c2&&elevator[pos] <= y2)
			ans2 += y2 - y1;
		else {
			int a1 = INF, a2 = INF;
			if (pos != 0)
				a1 = y1 - elevator[pos - 1];
			pos = lower_bound(elevator, elevator + c2, y2) - elevator;
			if (pos != c2)
				a2 = elevator[pos] - y2;
			ans2 += y2 - y1 + 2 * min(a1, a2);
		}
		ans2 += (x2 - x1) / v;
		if ((x2 - x1) % v != 0)
			ans2++;

		cout << min(ans1, ans2) << endl;
	}

	return 0;
}

你可能感兴趣的:(Codeforces)