#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;
}
来源:CSDN
作者:Intelligence1028
链接:https://blog.csdn.net/Intelligence1028/article/details/104503034