现在的位置: 首页 > 综合 > 正文

POJ 2464 Brownie Points II(树状数组+扫描线)

2019年02月11日 ⁄ 综合 ⁄ 共 1792字 ⁄ 字号 评论关闭

果然题意罗里吧嗦的题做法也很麻烦。。


给出二维平面上的一些点,Stan可以任选一个点作一条垂线,然后Ollie可以在垂线上再选一个点作水平线。在一、三象限的点数算Stan的分数,在二、四象限的点算Ollie的分数。

两个人都想要自己的分数最大。

问Stan分数的最大值,且有多种情况时,按大小顺序列出Ollie的所有可能得分(无重复)。


主要重点是维护两棵x轴上的树状数组,当前位置的左边有多少个点和右边有多少个点。

把坐标值离散化,把点按x的大小排序;从左往右扫描,所以先把点插入右边的树(即每个y有多少个点)。

每扫过一个x,先把该x上的点从右边的树删去,然后对该x处的垂线上的每个点求一次四个象限的点的个数;当往下一个x扫描时,把此时的x上的所有点再插入左边的树。


然后一些细节乱搞一下。

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <vector>
using namespace std;
#define MAXN 200010

int ny[MAXN];
int sl[MAXN], sr[MAXN];
int n, stan, st, tot;
vector<int> ollie;

inline int lowbit(int x)
{
    return x & -x;
}

int sum(int s[], int i)
{
    int ret = 0;
    while(i > 0)
    {
        ret += s[i];
        i -= lowbit(i);
    }
    return ret;
}

void add(int s[], int i, int val)
{
    while(i <= n)
    {
        s[i] += val;
        i += lowbit(i);
    }
}

struct Point
{
    int x, y;
    bool operator <(const Point &argu) const
    {
        return x < argu.x;
    }
}pp[MAXN];

int main()
{
//    freopen("C.in", "r", stdin);

    while(scanf("%d", &n) && n)
    {
        for(int i = 0; i < n; i++) scanf("%d%d", &pp[i].x, &pp[i].y), ny[i] = pp[i].y;
        sort(ny, ny + n);

        int cnty = 0;
        for(int i = 0; i < n; i++) if(ny[cnty] != ny[i]) ny[++cnty] = ny[i]; cnty++;
        for(int i = 0; i < n; i++) pp[i].y = lower_bound(ny, ny + cnty, pp[i].y) - ny + 1;

        sort(pp, pp + n); pp[n].x = pp[n - 1].x + 1;

        memset(sr, 0, sizeof(sr));
        memset(sl, 0, sizeof(sl));
        for(int i = 0; i < n; i++) add(sr, pp[i].y, 1);

        stan = -1, st = 0;
        for(int i = 0; i < n; i++)
        {
            if(pp[i].x != pp[i + 1].x)
            {
                for(int j = st; j <= i; j++) add(sr, pp[j].y, -1);
                int tmps = -1, tmpo = -1;
                for(int j = st; j <= i; j++)
                {
                    int a = sum(sr, cnty) - sum(sr, pp[j].y) + sum(sl, pp[j].y - 1);
                    int b = sum(sl, cnty) - sum(sl, pp[j].y) + sum(sr, pp[j].y - 1);
                    if(b == tmpo) tmps = min(tmps, a);
                    if(b >  tmpo) tmps = a, tmpo = b;
                }
                if(tmps >  stan) stan = tmps, ollie.clear();
                if(tmps == stan) ollie.push_back(tmpo);
                for(int j = st; j <= i; j++) add(sl, pp[j].y, 1);
                st = i + 1;
            }
        }
        sort(ollie.begin(), ollie.end());
        tot = unique(ollie.begin(), ollie.end()) - ollie.begin();
        printf("Stan: %d; Ollie:", stan);
        for(int i = 0; i < tot; i++) printf(" %d", ollie[i]);
        puts(";");
    }
    return 0;
}

抱歉!评论已关闭.