Codeforces Round #281 (Div. 2) C. Vasya and Basketball 枚举+二分

来源:互联网 发布:视频剪辑 for mac 编辑:程序博客网 时间:2024/05/16 19:28

思路:给定一个d,两队的分数可以在log(n)内求出:二分查找出最后一个不大于d的位置idx,则0~idx这idx+1次投球得分为2分,idx+1~n-1这n-idx-1次投球得分为3

所以只需枚举二分线d即可。开始时在最大最小值之间枚举,复杂度O(10^9)超时。观察数据量,其实枚举m+n个数即可。下面证明两者得到的最优解是等价的:

设最优解d,二分得到a队的位置为i (a[i] = x),b队的位置为j (b[j] = y) ,(d >= x,d >= y)。证明枚举到x和y时,其中覆盖了d的解

①若x > y,则枚举到x时,b[j + 1] > d >= x,a和b中的分界点与取d时相同

②若x = y,则枚举到x或y,都与d等价

③若x < y则枚举到y时,a[i + 1] > d >= y,a和b中的分界点与取d相同

特殊情况:由于从a、b的最小值枚举起,而d可能比二者的最小值还小,此时所有投球均取3分。

代码如下:

#include <cstdio>#include <algorithm>using namespace std;#define N 200005int a[N], b[N], d[2 * N];int binary_search(int x, int array[N], int bound){int l = 0, r = bound;while(l < r - 1){int mid = l + ((r - l) >> 1);if(array[mid] <= x)l = mid;elser = mid - 1;}if(array[r] <= x)return r;else if(array[l] <= x)return l;elsereturn -1;}int main(){int n, m, len = 0;int ans, final1, final2;scanf("%d", &n);for(int i = 0; i < n; ++i)scanf("%d", &a[i]), d[len ++] = a[i];sort(a, a + n);scanf("%d", &m);for(int i = 0; i < m; ++i)scanf("%d", &b[i]), d[len ++] = b[i];sort(b, b + m);final1 = 3 * n, final2 = 3 * m, ans = final1 - final2;for(int i = 0; i < len; ++i){int idx1 = binary_search(d[i], a, n - 1);int idx2 = binary_search(d[i], b, m - 1);int score1 = (idx1 + 1) * 2 + (n - idx1 - 1) * 3;int score2 = (idx2 + 1) * 2 + (m - idx2 - 1) * 3;int tmp = score1 - score2;if(ans < tmp)ans = tmp, final1 = score1, final2 = score2;else if(ans == tmp && score1 > final1)final1 = score1, final2 = score2;}printf("%d:%d\n", final1, final2);return 0;}


0 0