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

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).

Output

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

Sample Output

Stan: 7; Ollie: 2 3;

简述一下题意,给你一些点的x,y坐标,过一点做垂线,再做一条水平线,且该水平线必须经过已经被第一条垂线穿过的点,将所有点分成了4份,Stan是左下右上点个数之和,Ollie是左上右下,
求出Stan的值,使其最小值最大,并且输出该条垂线下,Stan取该值时,Ollie值的最大值,升序打印。
思路:读题意,求个数之和,想到二维树状数组,看数据范围,变成偏序问题,离散化后一维树状数组即可,本题的细节主要是在如何求这四份,树状数组可以求出左下区域,那么就分别维护每个点上下左右各有多少点,结合左下就可以求出其他区域,如图:

TL = 该点左侧的点-BL, TR = 该点上侧的点-TL, BR = 该点右侧的点-TR


细节代码中有注释(补到线段树和扫描线再做一次


using namespace std;
#define lowbit(x) ((x)&(-x))
typedef long long LL; const int maxm = 2e5+;
const int INF = 0x3f3f3f3f; int x[maxm], y[maxm], numx[maxm], numy[maxm], Left[maxm], Right[maxm], \
Upper[maxm], Lower[maxm], n, totx, toty, C[maxm], ally[maxm], allx[maxm], \
sumLeft[maxm], sumRight[maxm], sumUpper[maxm], sumLower[maxm], sumx[maxm], sumy[maxm], \
ans1[maxm], ans2[maxm];
bool vis[maxm]; void init() {
totx = toty = ;
memset(ans1, , sizeof(ans1)), memset(ans2, -, sizeof(ans2));
memset(C, , sizeof(C)), memset(numx, , sizeof(numx)), memset(numy, , sizeof(numy));
memset(sumx, , sizeof(sumx)), memset(sumy, , sizeof(sumy)), memset(vis, , sizeof(vis));
} void add(int pos, int val) {
for(; pos <= toty; pos += lowbit(pos))
C[pos] += val;
} int getsum(int pos) {
int ret = ;
for(; pos; pos -= lowbit(pos))
ret += C[pos];
return ret;
} struct Node {
int x, y;
Node(){}
bool operator<(const Node &a) const {
return x < a.x || (x == a.x && y < a.y);
}
} Nodes[maxm]; int main() {
while(scanf("%d", &n) && n) {
init();
// 读入并对x,y离散化
for(int i = ; i <= n; ++i) {
scanf("%d%d", &x[i], &y[i]);
allx[++totx] = x[i], ally[++toty] = y[i];
}
sort(allx+, allx++totx), sort(ally+,ally++toty);
int lenx = unique(allx+, allx++totx)-allx-, leny = unique(ally+,ally++toty)-ally-;
int nodenum = ;
for(int i = ; i <= n; ++i) {
Nodes[++nodenum].x = lower_bound(allx+,allx+lenx+, x[i]) - allx;
Nodes[nodenum].y = lower_bound(ally+,ally+leny+, y[i]) - ally;
}
sort(Nodes+, Nodes+nodenum+);
// 求出每个点上下左右垂直有多少个点
for(int i = ; i <= nodenum; ++i) {
Lower[i] = numx[Nodes[i].x]++;
Left[i] = numy[Nodes[i].y]++;
}
for(int i = ; i <= nodenum; ++i) {
Upper[i] = numx[Nodes[i].x] - Lower[i] - ;
Right[i] = numy[Nodes[i].y] - Left[i] - ;
}
// 求出坐标xi=1,2,的左侧 yi=1,2,的下侧 一共有多少个点 水平/垂直线(包括该线)
for(int i = ; i <= lenx; ++i) {
sumx[i] = sumx[i-] + numx[i];
}
for(int i = ; i <= leny; ++i) {
sumy[i] = sumy[i-] + numy[i];
}
// 计算每个点上下左右侧一共有几个点
for(int i = ; i <= nodenum; ++i) {
int x = Nodes[i].x, y = Nodes[i].y;
sumLeft[i] = sumx[x-];
sumRight[i] = sumx[lenx] - sumx[x];
sumLower[i] = sumy[y-];
sumUpper[i] = sumy[leny] - sumy[y];
}
for(int i = ; i <= nodenum; ++i) {
int x = Nodes[i].x, y = Nodes[i].y;
int BL = getsum(y-) - Lower[i];
int TL = sumLeft[i] - BL - Left[i];
int TR = sumUpper[i] - TL - Upper[i];
int BR = sumLower[i] - BL - Lower[i];
add(y, );
if(BL + TR < ans1[x]) {
ans1[x] = BL + TR, ans2[x] = TL + BR;
} else if(BL + TR == ans1[x]) ans2[x] = max(ans2[x], TL + BR);
}
int ans = ;
for(int i = ; i <= lenx; ++i)
if(ans1[i] < INF)
ans = max(ans, ans1[i]);
printf("Stan: %d; Ollie:",ans);
for(int i = ; i <= lenx; ++i)
if(ans1[i] == ans) vis[ans2[i]] = true;
for(int i = ; i <= n; ++i)
if(vis[i])
printf(" %d", i);
printf(";\n");
}
}


												

Day6 - E - Brownie Points II POJ - 2464的更多相关文章

  1. hdu 1156 && poj 2464 Brownie Points II (BIT)

    2464 -- Brownie Points II Problem - 1156 hdu分类线段树的题.题意是,给出一堆点的位置,stan和ollie玩游戏,stan通过其中一个点画垂线,ollie通 ...

  2. UVA10869 - Brownie Points II(线段树)

    UVA10869 - Brownie Points II(线段树) 题目链接 题目大意:平面上有n个点,Stan和Ollie在玩游戏,游戏规则是:Stan先画一条竖直的线作为y轴,条件是必需要经过这个 ...

  3. UVA 10869 - Brownie Points II(树阵)

    UVA 10869 - Brownie Points II 题目链接 题意:平面上n个点,两个人,第一个人先选一条经过点的垂直x轴的线.然后还有一个人在这条线上穿过的点选一点作垂直该直线的线,然后划分 ...

  4. POJ - 2464 Brownie Points II 【树状数组 + 离散化】【好题】

    题目链接 http://poj.org/problem?id=2464 题意 在一个二维坐标系上 给出一些点 Stan 先画一条过一点的水平线 Odd 再画一条 过Stan那条水平线上的任一点的垂直线 ...

  5. POJ 2464 Brownie Points II (树状数组,难题)

    题意:在平面直角坐标系中给你N个点,stan和ollie玩一个游戏,首先stan在竖直方向上画一条直线,该直线必须要过其中的某个点,然后ollie在水平方向上画一条直线,该直线的要求是要经过一个sta ...

  6. POJ 2464 Brownie Points II(树状数组)

    一开始还以为对于每根竖线,只要与过了任意一点的横线相交都可以呢,这样枚举两条线就要O(n^2),结果发现自己想多了... 其实是每个点画根竖线和横线就好,对于相同竖线统计(一直不包含线上点)右上左下总 ...

  7. POJ 2464 Brownie Points II --树状数组

    题意: 有点迷.有一些点,Stan先选择某个点,经过这个点画一条竖线,Ollie选择一个经过这条直接的点画一条横线.Stan选这两条直线分成的左下和右上部分的点,Ollie选左上和右下部分的点.Sta ...

  8. HDOJ-1156 Brownie Points II 线段树/树状数组(模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=1156 在一张二位坐标系中,给定n个点的坐标,玩一个划线游戏(线必须穿过点),Stan先手画一条垂直的线,然后Ol ...

  9. [转载]完全版线段树 by notonlysuccess大牛

    原文出处:http://www.notonlysuccess.com/ (好像现在这个博客已经挂掉了,在网上找到的全部都是转载) 今天在清北学堂听课,听到了一些很令人吃惊的消息.至于这消息具体是啥,等 ...

随机推荐

  1. Unity3D~纹理格式

    因为之前自己从来没有好好看过这部分,一直都是用的DXT压缩图片,结果发现原来ios是不支持DXT的, 还不知道我项目那么卡是不是这部分引起的, 但愿是~这样应该就可以解决游戏在ios上只有6.8帧的问 ...

  2. CentOS7编译安装httpd-2.4.41

    安装参考环境: CentOS Linux release 7.5.1804 (Core) 一.安装依赖包 httpd安装的依赖包 # yum -y install pcre-devel # yum - ...

  3. 本地启动tomcat的时候报java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space

    1.问题:我在tomcat中放入了大量的war包,启动的时候报:java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: ...

  4. Oracle常用命令复习(备考资料)

    Oracle期末考试复习资料,大概的总结了常用的命令,不包括基础理论知识,有的不太考的东西没有整理.资料整理是在有道云笔记里完成的,在这里重新编辑太麻烦了,就附个链接了. 文档:Oracle命令复习2 ...

  5. Django 学习之cookie与session

    一.cookie和session的介绍 cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生. cookie ...

  6. 设计模式课程 设计模式精讲 8-10 单例设计模式-ThreadLocal线程单例

    1 课程讲解 1.1 应用场景 2 代码演练 2.1 threadLocal应用 1 课程讲解 1.1 应用场景 多线程的时候: 使用同步锁使用时间换空间的方式,(线程排队时间比较长) 而使用thre ...

  7. 使用SourceTree的注意事项

    1.我使用SourceTree时,使用的下面的配置全局忽略: *~ .DS_Store xcuserdata 2. 远程仓库的url路径不要使用域名,而应该使用ip地址.否则会显示“这是一个无效的ur ...

  8. 自定义Model类

    声明文件 #import <Foundation/Foundation.h> @interface OrderRecordModel : NSObject @property (nonat ...

  9. SpringMVC的@ControllerAdvice注解

    @ControllerAdvice顾名思义,他是一个Controller的增强,是一个异常处理类.常用于实现下面三个方面的功能: 1.处理全局异常,结合方法型注解@ExceptionHandler,用 ...

  10. _CrtIsValidHeapPointer(pUserData)

    程序遇到如题的运行时报错,参考下面这段文字,采取将自定义类的对象定义改为new方式生成后问题解决. !!Expression: _CrtIsValidHeapPointer(pUserData) vo ...