首页 > 代码库 > UVA 10869 - Brownie Points II(树状数组)
UVA 10869 - Brownie Points II(树状数组)
UVA 10869 - Brownie Points II
题目链接
题意:平面上n个点,两个人,第一个人先选一条经过点的垂直x轴的线,然后另一个人在这条线上穿过的点选一点作垂直该直线的线,然后划分出4个象限,第一个人得到分数为1,3象限,第二个人为二四象限,问第一个个人按最优取法,能得到最小分数的最大值,和这个值下另一个人的得分可能情况
思路:树状数组,可以枚举一点,如果能求出右上和左下点的个数就好办了,其实用一个树状数组,把y坐标离散化掉,然后记录进来,然后把点按x从左往右,每次删掉点后查询当前高度向上的点的个数,这样就能得到右上角点的个数,同理也能求左下角,能处理这步就好办了,最后注意答案要取重并且递增,用set就ok了
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <set> using namespace std; #define lowbit(x) (x&(-x)) const int N = 200005; struct Point { int x, y, rank, ans, Mi; int xn, yn; } p[N]; int bit[N]; set<int> out; void add(int x, int v) { while (x < N) { bit[x] += v; x += lowbit(x); } } int get(int x) { int ans = 0; while (x > 0) { ans += bit[x]; x -= lowbit(x); } return ans; } int get(int l, int r) { return get(r) - get(l - 1); } bool cmpy(Point a, Point b) { return a.y < b.y; } bool cmpx(Point a, Point b) { if (a.x == b.x) return a.y > b.y; return a.x < b.x; } bool cmpx2(Point a, Point b) { if (a.x == b.x) return a.y < b.y; return a.x > b.x; } int n, top; void init() { memset(bit, 0, sizeof(bit)); for (int i = 0; i < n; i++) { scanf("%d%d", &p[i].x, &p[i].y); p[i].ans = 0; p[i].xn = p[i].yn = 0; } sort(p, p + n, cmpy); } void solve() { top = 1; for (int i = 0; i < n; i++) { if (i && p[i].y != p[i - 1].y) top++; p[i].rank = top; add(p[i].rank, 1); } for (int i = 0; i < n; i++) { int j; int len = 0; for (j = i; p[i].y == p[j].y && j < n; j++) len++; for (j = i; p[i].y == p[j].y && j < n; j++) p[j].yn = len; i = j - 1; } sort(p, p + n, cmpx); for (int i = 0; i < n; i++) { add(p[i].rank, -1); p[i].ans += get(p[i].rank + 1, top); } for (int i = 0; i < n; i++) { int j; int len = 0; for (j = i; p[i].x == p[j].x && j < n; j++) len++; for (j = i; p[i].x == p[j].x && j < n; j++) p[j].xn = len; i = j - 1; } memset(bit, 0, sizeof(bit)); for (int i = 0; i < n; i++) add(p[i].rank, 1); sort(p, p + n, cmpx2); for (int i = 0; i < n; i++) { add(p[i].rank, -1); p[i].ans += get(1, p[i].rank - 1); } for (int i = 0; i < n; i++) { int j; int Min = 1000000000; for (j = i; p[i].x == p[j].x && j < n; j++) Min = min(Min, p[j].ans); for (j = i; p[i].x == p[j].x && j < n; j++) p[j].Mi = Min; i = j - 1; } int Max = 0; out.clear(); for (int i = 0; i < n; i++) { if (p[i].Mi != p[i].ans) continue; if (p[i].ans > Max) { Max = p[i].ans; out.clear(); out.insert(n - p[i].ans - p[i].xn - p[i].yn + 1); } else if (p[i].ans == Max) { out.insert(n - p[i].ans - p[i].xn - p[i].yn + 1); } } printf("Stan: %d; Ollie:", Max); for (set<int>::iterator it = out.begin(); it != out.end(); it++) printf(" %d", *it); printf(";\n"); } int main() { while (~scanf("%d", &n) && n) { init(); solve(); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。