一开始还以为对于每根竖线,只要与过了任意一点的横线相交都可以呢,这样枚举两条线就要O(n^2),结果发现自己想多了。。。

  其实是每个点画根竖线和横线就好,对于相同竖线统计(一直不包含线上点)右上左下总点数的最小值,最后不同竖线求一个最大值。对于每条等于这个最小值最大化的竖线都找一个右下与左上的最大值,排序输出即可。注意这儿排序后需要去重

  思想倒是不难,主要就是麻烦。只需要分别离散化x轴,y轴的点,然后枚举每个点找到四个方向的其他总点数,这儿用树状数组可以简单解决。但是注意空间问题不能开二维,开一维排序x轴,再左右扫一遍,一边计算一边添加点即可,注意x y轴线上的点要减去。先扫一边找到最小值最大化的值与每条竖线包含哪些点,再扫一遍找到等于那个值的竖线中的最大右下左上和

代码写得很麻烦

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=<<;
const double Pi=acos(-1.0);
const int Max=;
int bit[Max];
struct node
{
int xx1,yy1;
int lup,rup,ldo,rdo;
} poi[Max];
int n;
bool cmp1(struct node p1,struct node p2)
{
if(p1.xx1==p2.xx1)
return p1.yy1<p2.yy1;
return p1.xx1<p2.xx1;
}
bool cmp2(struct node p1,struct node p2)
{
return p1.yy1<p2.yy1;
}
int lowbit(int x)
{
return x&(-x);
}
void Add(int y)
{
while(y<=n)
{
bit[y]++;
y+=lowbit(y);
}
return;
}
int Sum(int y)
{
if(!y)
return ;
int sum=;
while(y>)
{
sum+=bit[y];
y-=lowbit(y);
}
return sum;
}
void Dtz()//离散化
{
sort(poi,poi+n,cmp2);
int m=;
poi[n].yy1=Inf;
for(int i=; i<n; i++)
{
if(poi[i].yy1!=poi[i+].yy1)//注意不能和前一个进行比较,因为前一个已经被赋值
poi[i].yy1 = m++;
else
poi[i].yy1 = m;
} sort(poi,poi+n,cmp1);
m=;
poi[n].xx1=Inf;
for(int i=; i<n; i++)
{
if(poi[i].xx1!=poi[i+].xx1)
poi[i].xx1 = m++;
else
poi[i].xx1 = m;
}
return ;
}
int tem[Max],minx[Max],pos[Max];
void Solve()
{
int sum;
memset(bit,,sizeof(bit));
for(int i=; i<n; i++) //边添加边查询
{
if(i!=&&poi[i].xx1==poi[i-].xx1)
sum++;
else
sum=;
poi[i].ldo=Sum(poi[i].yy1-)-sum;//减一,避免y轴相同的点被计算
poi[i].lup=Sum(n)-Sum(poi[i].yy1);
Add(poi[i].yy1);
} memset(bit,,sizeof(bit));
for(int i=n-; i>=; i--)
{
if(i!=n-&&poi[i].xx1==poi[i+].xx1)
sum++;
else
sum=;
poi[i].rdo=Sum(poi[i].yy1-);
poi[i].rup=Sum(n)-Sum(poi[i].yy1)-sum;
Add(poi[i].yy1);
} int manx=,mans;//统计
int coun=,cnt=;
minx[]=Inf;
for(int i=; i<n; i++)//计算最小值最大的是多少
{
if(!i||poi[i].xx1==poi[i-].xx1)
{
if(poi[i].rup+poi[i].ldo<minx[coun])
minx[coun]=poi[i].rup+poi[i].ldo;
}
else
{
manx=max(manx,minx[coun]);
pos[coun++]=i;//每条同x轴的最后一个的后一个下标
minx[coun]=Inf;
if(poi[i].rup+poi[i].ldo<minx[coun])
minx[coun]=poi[i].rup+poi[i].ldo;
}
}
pos[coun]=n;
manx=max(manx,minx[coun]); for(int i=;i<=coun;i++)
{
if(minx[i]==manx)//此x轴可用
{
mans=;
for(int j=i==?:pos[i-];j<pos[i];j++)
mans=max(mans,poi[j].lup+poi[j].rdo);
tem[cnt++]=mans;
}
} printf("Stan: %d; Ollie:",manx);
sort(tem,tem+cnt);
int cntt=;
for(int i=;i<cnt;i++)//去重
if(tem[i]!=tem[cntt])
tem[++cntt]=tem[i];
for(int i=; i<=cntt; i++)
printf(" %d",tem[i]);
printf(";\n");
return ;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
for(int i=; i<n; i++)
scanf("%d %d",&poi[i].xx1,&poi[i].yy1);
Dtz();//离散化
Solve();
}
return ;
}

POJ 2464 Brownie Points II(树状数组)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. POJ 2155 Matrix(二维树状数组,绝对具体)

    Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 20599   Accepted: 7673 Descripti ...

  7. poj 3321:Apple Tree(树状数组,提高题)

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18623   Accepted: 5629 Descr ...

  8. POJ 2299 Ultra-QuickSort 逆序数 树状数组 归并排序 线段树

    题目链接:http://poj.org/problem?id=2299 求逆序数的经典题,求逆序数可用树状数组,归并排序,线段树求解,本文给出树状数组,归并排序,线段树的解法. 归并排序: #incl ...

  9. poj 3321 Apple Tree(一维树状数组)

    题目:http://poj.org/problem?id=3321 题意: 苹果树上n个分叉,Q是询问,C是改变状态.... 开始的处理比较难,参考了一下大神的思路,构图成邻接表 并 用DFS编号 白 ...

随机推荐

  1. [转]Android 学习资料分享(2015 版)

    转 Android 学习资料分享(2015 版) 原文地址:http://www.jianshu.com/p/874ff12a4c01 目录[-] 我是如何自学Android,资料分享(2015 版) ...

  2. 【leetcode】Combinations (middle)

    Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For exampl ...

  3. 【XLL API 函数】xlSheetNm

    从外部引用包含的工作表ID返回工作表或宏表名称,或是当前表名称. 原型 Excel12(xlSheetNm, LPXLOPER12 pxRes, 1, LPXLOPER12 pxExtref); 参数 ...

  4. java课后作业7

    9.页实验 下列语句哪一个将引起编译错误?为什么?哪一个会引起运行时错误?为什么? m=d; d=m; d=(Dog)m; d=c; c=(Cat)m; 答: d=m;和d=c;引起编译错误: 原因: ...

  5. windows系统查看80端口被占用的程序并结束该程序运行

    一.背景 最近系统更新以后,我在Idea中适用80端口启动项目的时候发现80端口被占用了,就查了资料看怎么找到占用80端口的程序并结束其运行,下面把解决方式共享给大家. 二.解决步骤 1.首先打开控制 ...

  6. asp.net 防止按钮重复提交

    1.将按钮属性设置如下: <asp:Button ID="btConfirm" runat="server" Text="Confirm&quo ...

  7. JavaWeb学习--Servlet认识

    Servlet开发 用户在浏览器中输入一个网址并回车,浏览器会向服务器发送一个HTTP请求.服务器端程序接受这个请求,并对请求进行处理,然后发送一个回应.浏览器收到回应,再把回应的内容显示出来.这种请 ...

  8. Javaweb---Servlet过滤器

    Servlet过滤器从字面上的字意理解为景观一层次的过滤处理才达到使用的要求,而其实Servlet过滤器就是服务器与客户端请求与响应的中间层组件,在实际项目开发中Servlet过滤器主要用于对浏览器的 ...

  9. sql server 对象资源管理器(一)

    当需要查看具体数据库的所有用户表.存储过程等创建修改等脚本的时候,可以借用视图中的对象资源管理器的详细信息里面获取. 具体操作如下图所示:

  10. Android自学指导

    如果想自学Android,以下的文章可以作为参考: 如何自学Android(Gityuan) 那两年炼就的Android内功修养(老罗的Android之旅)