一开始还以为对于每根竖线,只要与过了任意一点的横线相交都可以呢,这样枚举两条线就要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. suse linux 10 下配置vpn服务器(pptp)

     一.安装所需的软件包:      pptpd-*.rpm      ppp-*.rpm      pptp-*.rpm     一般情况下系统已经将pptp和ppp包安装好了,所以只需安装pptpd ...

  2. sql server 行转列(转载)

    SQL Server中行列转换 Pivot UnPivot PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PI ...

  3. 1.SQL语句入门

    --SQL语句入门-- --1.sql语言是解释语言 --2.它不区分大小写 --3.没有"",所有字符或者字符串都使用''包含 --4.sql里面也有类似于c#的运算符 -- 算 ...

  4. xcode7 免费真机调试

    原文链接:http://www.cnblogs.com/tandaxia/p/4839997.html 刚新安装了Xcode7 Version 7.1 beta , 据说这个版本可以免费真机调试,于是 ...

  5. IOS-Uikit框架介绍

    •UIKit可识别三种类型的输入事件: –触摸事件 –运动(加速计)事件 –远程控制事件 IKit框架将触击信息封装为一个UIEvent对象,并派发给恰当的视图(有关UIKit如何将事件递送给您的视图 ...

  6. GCD的使用

    什么是 GCD Grand Central Dispatch (GCD) 是 Apple 开发的一个多核编程的解决方法.该方法在 Mac OS X 10.6 雪豹中首次推出,并随后被引入到了 iOS4 ...

  7. August 28th 2016 Week 36th Sunday

    What doesn't kill you makes you stronger. 那些没有彻底击败你的东西只会让你更强大. Where there is life, there is hope, a ...

  8. 添加本地jar到Maven库

    转自:http://dk05408.iteye.com/blog/2170986 上传: mvn install:install-file -Dfile=D:/workspace/p2p_server ...

  9. oracle dataguard (一)

    一.什么是data guard及data guard的工作原理 Data Guard 是一个集合,由一个primary数据库(生产数据库)及一个或多个standby数据库(最多9个)组成.组成Data ...

  10. 困难的串(dfs)

    困难的串 题意: 如果一个字符串包含两个相邻的重复子串,则称它是“容易的串”,其他串称为“困难的串”.例如,                 BB.ABCDABCD都是容易的串,而D.DC.ABDAD ...