果然题意罗里吧嗦的题做法也很麻烦。。
给出二维平面上的一些点,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; }