A. Mind the Gap
传送门:http://codeforces.com/contest/967/problem/A
题目大意:
给定n个飞机着陆时间点,以及时间差s,并且起飞和着陆需要1分钟,即时间差为s+1。现在要插入一个飞机起飞的时间点,使得这n+1个时间点仍然保持两两之间相差s+1分钟。
AC代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cstdlib> #include<utility> #include<algorithm> #include<utility> #include<queue> #include<vector> #include<set> #include<stack> #include<cmath> #include<map> #define P pair<int,int> #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<iostream> #include<cstdio> #include<cstring> #include<string> #include<cstdlib> #include<utility> #include<algorithm> #include<utility> #include<queue> #include<vector> #include<set> #include<stack> #include<cmath> #include<map> #define P pair<int,int> #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<iostream> #include<cstdio> #include<cstring> #include<string> #include<cstdlib> #include<utility> #include<algorithm> #include<utility> #include<queue> #include<vector> #include<set> #include<stack> #include<cmath> #include<map> #define P pair<int,int> #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; }