24h購物| | PChome| 登入
2013-10-11 08:57:45| 人氣1,840| 回應0 | 上一篇 | 下一篇

[UVA][離散化&掃描線&BIT] 10869 - Brownie Points II

推薦 0 收藏 0 轉貼0 訂閱站台

Problem E: Brownie Points II

Stan and Ollie play the game of Odd Brownie Points. Some brownie points are located in the plane, at integer coordinates. Stan plays first and places a vertical line in the plane. The line must go through a brownie point and may cross many (with the same x-coordinate). Then Ollie places a horizontal line that must cross a brownie point already crossed by the vertical line.

Those lines divide the plane into four quadrants. The quadrant containing points with arbitrarily large positive coordinates is the top-right quadrant.

The players score according to the number of brownie points in the quadrants. If a brownie point is crossed by a line, it doesn't count. Stan gets a point for each (uncrossed) brownie point in the top-right and bottom-left quadrants. Ollie gets a point for each (uncrossed) brownie point in the top-left and bottom-right quadrants.

Stan and Ollie each try to maximize his own score. When Stan plays, he considers the responses, and chooses a line which maximizes his smallest-possible score.

Input contains a number of test cases. The data of each test case appear on a sequence of input lines. The first line of each test case contains a positive odd integer 1 < n < 200000 which is the number of brownie points. Each of the following n lines contains two integers, the horizontal (x) and vertical (y) coordinates of a brownie point. No two brownie points occupy the same place. The input ends with a line containing 0 (instead of the n of a test).

For each input test, print a line of output in the format shown below. The first number is the largest score which Stan can assure for himself. The remaining numbers are the possible (high) scores of Ollie, in increasing order.

Sample input

11
3 2
3 3
3 4
3 6
2 -2
1 -3
0 0
-3 -3
-3 -2
-3 -4
3 -7
0

Output for sample input

Stan: 7; Ollie: 2 3;

P. Rudnicki

題目描述:


Stan 和 Ollie 玩一個遊戲,平面上有點,Stan 選擇一條垂直線後,換 Ollie 選擇一條水平線,
這兩條線必然要交於一點,Stan 得分為左上右下象限的點個數,Ollie 則拿到左下右上的點個數。

而 Stan 玩的時候,會選擇一條可以使得最低得分最高,Ollie 則會在他選後,找到一條使得他得分最高。

求 Stan 的得分,以及 Ollie 有可能會拿到哪些得分,並且由小到大輸出。

題目解法:


對輸入的 y 座標離散化,以方便藉由 binary indexed tree 查找象限點個數。
維護兩個 BIT,紀錄垂直線的左側和右側狀態。

利用掃描線,由左至右掃描每一點,由於得分不計算軸上的點個數。
因此,相同垂直線上要同時討論,依序將右側的點,從右側 BIT 去除,加入左側 BIT。

#include <stdio.h>
#include <vector>
#include <string.h>
#include <algorithm>
using namespace std;
struct Pt {
    int x, y, dy;
    Pt(int a=0, int b=0):
        x(a), y(b), dy(0) {}
    bool operator<(const Pt &a) const {
        if(x != a.x)
            return x < a.x;
        return y < a.y;
    }
};
bool cmp(Pt a, Pt b) {
    return a.y < b.y;
}
Pt D[200005];
// binary indexed tree.
void modify(int idx, int val, int n, int C[]) {
    while(idx <= n) {
        C[idx] += val;
        idx += idx&(-idx);
    }
}
int query(int idx, int C[]) {
    int ret = 0;
    while(idx) {
        ret += C[idx];
        idx -= idx&(-idx);
    }
    return ret;
}
int left[200005], right[200005];
int main() {
    int n, m;
    int i, j, k;
    while(scanf("%d", &n) == 1 && n) {
        for(i = 0; i < n; i++)
            scanf("%d %d", &D[i].x, &D[i].y);
        sort(D, D+n, cmp);
        int prevy = D[0].y-1;
        for(i = 0, m = 0; i < n; i++) {
            if(D[i].y != prevy) {
                m++;
                prevy = D[i].y;
            }
            D[i].dy = m;
        }
        sort(D, D+n);
        // pre-process.
        memset(right, 0, 4*m+4);
        memset(left, 0, 4*m+4);
        int rsize = n, lsize = 0;
        for(i = 0; i < n; i++) {
            modify(D[i].dy, 1, m, right);
        }
        // start.
        int previ = 0;
        int stan = -1;
        vector<int> olli;
        for(i = 1; i <= n; i++) {
            if(D[i].x != D[i-1].x || i == n) {//[previ, i-1]
                for(j = previ; j < i; j++) {
                    modify(D[j].dy, -1, m, right);
                    rsize--;
                }
                int a, b = -1;
                int ta, tb;
                for(j = previ; j < i; j++) {
                    ta = (rsize-query(D[j].dy, right))+query(D[j].dy-1, left);//top-right + bottom-left
                    tb = (lsize-query(D[j].dy, left))+query(D[j].dy-1, right);//top-left + bottom-right
                    if(tb > b)
                        b = tb, a = ta;
                    if(tb == b)
                        a = min(a, ta);
                }
                if(a > stan)
                    stan = a, olli.clear();
                if(a == stan)
                    olli.push_back(b);
                for(j = previ; j < i; j++) {
                    modify(D[j].dy, 1, m, left);
                    lsize++;
                }
                previ = i;
            }
        }
        sort(olli.begin(), olli.end());
        vector<int>::iterator it = unique(olli.begin(), olli.end());
        olli.resize(distance(olli.begin(), it));
        printf("Stan: %d; Ollie:", stan);
        for(i = 0; i < olli.size(); i++)
            printf(" %d", olli[i]);
        puts(";");
    }
    return 0;
}

台長: Morris
人氣(1,840) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 教育學習(進修、留學、學術研究、教育概況) | 個人分類: UVA |
此分類下一篇:[UVA][MST&窮舉] 1040 - The Traveling Judges Problem
此分類上一篇:[UVA] 1039 - Simplified GSM Network

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文