杭电OJ 1156(C++)

那年仲夏 提交于 2020-02-25 21:09:53
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 200002;

int l[MAXN], r[MAXN]; //垂线左侧的点,垂线右侧的点
int y[MAXN]; //y轴坐标
int n, w;

struct Line //垂直于x轴的直线
{
    int x, y;
    friend bool operator < (Line a, Line b) {
        return a.x < b.x;
    }
}line[MAXN];

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

void add(int t[], int x, int v) 
{
    while (x <= w) 
    {
        t[x] += v;
        x += lowbit(x);
    }
}

int sum(int t[], int x) 
{
    int res = 0;
    while (x > 0) 
    {
        res += t[x];
        x -= lowbit(x);
    }
    return res;
}

int main(void) 
{
    while (cin >> n)
    {
        if (n == 0)
            break;
        for (int i = 0; i < n; i++) 
        {
            cin >> line[i].x >> line[i].y;
            y[i] = line[i].y;
        }
        sort(y, y + n); //y轴坐标离散化
        w = unique(y, y + n) - y;
        sort(line, line + n); //按x轴坐标从小到大排序
        memset(l, 0, sizeof(l));
        memset(r, 0, sizeof(r));
        for (int i = 0; i < n; i++)
        {
            add(r, lower_bound(y, y + w, line[i].y) + 1 - y, 1);
        }
        //Stan是其可以获得的最大的最小值
        //st保存重复x坐标出现的起点
        int Stan = -1, st = 0;
        //保存Ollie可能的结果
        vector<int> Ollie;
        for (int i = 1; i <= n; i++)
        {
            if (i == n || line[i].x != line[i - 1].x)
            { //把重复的点从右侧BIT中删除
                for (int j = st; j < i; j++)
                {
                    add(r, lower_bound(y, y + w, line[j].y) + 1 - y, -1);
                }   
                int stan = -1, ollie = -1;
                for (int j = st; j < i; j++)
                { //扫描x坐标重复的点,枚举平行于x轴的直线
                    int f = lower_bound(y, y + w, line[j].y) + 1 - y;
                    int s = sum(l, f - 1) + sum(r, w) - sum(r, f);
                    int o = sum(l, w) - sum(l, f) + sum(r, f - 1);
                    if (o > ollie)
                    {
                        ollie = o;
                        stan = s;
                    }
                    else if (o == ollie)
                    {
                        stan = min(stan, s);
                    }
                }
                if (stan > Stan)
                {
                    Stan = stan;
                    Ollie.clear();
                    Ollie.push_back(ollie);
                }
                else if (stan == Stan)
                {
                    Ollie.push_back(ollie);
                }
                for (int j = st; j < i; j++)
                { //将重复的点加入左侧的BIT
                    add(l, lower_bound(y, y + w, line[j].y) + 1 - y, 1);
                }
                st = i;
            }
        }
        sort(Ollie.begin(), Ollie.end());
        int len = unique(Ollie.begin(), Ollie.end()) - Ollie.begin();
        cout << "Stan: " << Stan << "; Ollie:";
        for (int i = 0; i < len; i++)
            cout << " " << Ollie[i];
        cout << ";" << endl;
    }
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!