poj2464扫描线好题,回头再做
扫描线+区间更新
题解
/*
st[i],ol[i]表示y坐标大于y[i]和小于y[i]的点
两颗线段树建立在y轴上,区间[l,r]ol线选在[l,r]时st的分数
每次查询完成后再更新一次
遍历每条st线上的ol线,这是单点查询
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
#define N 200005
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1)) struct Point{
int x,y;
void get(){scanf("%d%d",&x,&y);}
bool operator<(const Point & b)const
{ return x<b.x; }
} p[N];
struct node{//线段树结点
int lft,rht;
int flag[];
int mid(){return MID(lft,rht);}
void init(int a,int b){flag[]=a;flag[]=b;}
};
int n,m,mi;
vector<int> mx;
map<int,int> H;
int y[N],st[N],ol[N];//离散化数轴,大于等于y[i]的点数,小于等于y[i]的点
struct Segtree{
node tree[N*];
void down(int ind){
for(int i=;i<;i++){
tree[LL(ind)].flag[i]+=tree[ind].flag[i];
tree[RR(ind)].flag[i]+=tree[ind].flag[i];
tree[ind].flag[i]=;
}
}
void build(int lft,int rht,int ind){
tree[ind].lft=lft;tree[ind].rht=rht;
tree[ind].init(,);
if(lft==rht) tree[ind].init(st[lft],ol[lft]);
else {
int mid=tree[ind].mid();
build(lft,mid,LL(ind));
build(mid+,rht,RR(ind));
}
}
void update(int st,int ed,int ind,int type,int valu){
int lft=tree[ind].lft,rht=tree[ind].rht;
if(st<=lft && ed>=rht)
tree[ind].flag[type]+=valu;
else {
down(ind);
int mid=tree[ind].mid();
if(st<=mid) update(st,ed,LL(ind),type,valu);
if(ed>mid) update(st,ed,LL(ind),type,valu);
}
}
void query(int pos,int ind,int &mi,int &mx){
if(tree[ind].lft==tree[ind].rht){
mi=tree[ind].flag[];
mx=tree[ind].flag[];
}
else {
down(ind);
int mid=tree[ind].mid();
if(pos<=mid) return query(pos,LL(ind),mi,mx);
if(pos>mid) return query(pos,RR(ind),mi,mx);
}
}
}seg;
int main(){
while(scanf("%d",&n),n){
H.clear();mx.clear();mi=m=; int id1=,id2=;
for(int i=;i<n;i++){
p[i].get();
y[i]=p[i].y;
}
sort(y,y+n);
sort(p,p+n);//把点按从左往右顺序排好
H[y[]]=;
for(int i=;i<n;i++)//遍历一次纵坐标
if(y[m]!=y[i]){
st[m]=n-i;//高于y[i]的点数
y[++m]=y[i];
ol[m]=i;//低于y[i]的点数
H[y[m]]=m;
}
st[m]=;
seg.build(,m,);
while(id1<n){
id2=id1;
while(p[id1].x==p[id2].x){//这一步删掉被st线穿过的点
//不是最低的点
if(p[id2].y!=y[]) //ol线低于p[id2].y情况的st分数就少了一份
seg.update(H[y[]],H[p[id2].y]-,,,-);
//不是最高的点
if(p[id2].y!=y[m]) //ol线高于p[id2].y的时候
seg.update(H[p[id2].y]+,H[y[m]],,,-);
if(++id2>=n) break;
}
int mii=n,mxx=;
for(int i=id1;i<id2;i++){//依次在st线上的点建立ol线并进行查询,找到使st得分最低的那个点
int tmp1,tmp2;
seg.query(H[p[i].y],,mii,mxx);
mii=min(mii,tmp1);
mxx=max(mxx,tmp2);
} if(mii==mi) mx.push_back(mxx);//找到了ol的新解
else if(mii>mi){//找到了st的更优解
mi=mii;
mx.clear();mx.push_back(mxx);
}
//再更新一次,把这条线上删掉的反向加回去:因为扫描线往后扫描这条线上原来应该属于ol的现在属于st,原来属于st的现在应该属于ol
for(int i=id1;i<id2;i++){
if(p[i].y!=y[])
seg.update(H[y[]],H[p[i].y]-,,,);
if(p[i].y!=y[m])
seg.update(H[p[i].y]+,H[y[m]],,,);
}
id1=id2;
}
sort(mx.begin(),mx.end());
mx.erase(unique(mx.begin(),mx.end()),mx.end());
printf("Stan: %d; Ollie:",mi);
for(int i=;i<mx.size();i++)
printf(" %d",mx[i]);
printf(";\n");
}
return ;
}
poj2464扫描线好题,回头再做的更多相关文章
- cf276E 两棵线段树分别维护dfs序和bfs序,好题回头再做
搞了一晚上,错了,以后回头再来看 /* 对于每次更新,先处理其儿子方向,再处理其父亲方向 处理父亲方向时无法达到根,那么直接更新 如果能达到根,那么到兄弟链中去更新,使用bfs序 最后,查询结点v的结 ...
- poj2464扫描线好题,树状数组解法
用树状数组解比线段树快了好多,难度也下降许多 分别用两个树状数组维护当前扫描线左侧和右侧的点,离散化y轴即可 #include<iostream> #include<cstring& ...
- uva12436 回头再做一次
线段树维护等差数列,结点维护首项+公差即可 #include <cstdio> #include <cstring> #include <algorithm> us ...
- hdu4942线段树模拟rotate操作+中序遍历 回头再做
很有意思的题目,详细题解看这里 https://blog.csdn.net/qian99/article/details/38536559 自己的代码不知道哪里出了点问题 /* rotate操作不会改 ...
- Go: LeetCode简单题,简单做(sort.Search)
前言 正值端午佳节,LeetCode也很懂.这两天都是简单题,早点做完去包粽子. 故事从一道简单题说起 第一个错误的版本 简单题 你是产品经理,目前正在带领一个团队开发新的产品.不幸的是,你的产品的最 ...
- CozyRSS开发记录3-标题栏再加强
CozyRSS开发记录3-标题栏再加强 1.更精炼的标题栏 接下来,我们把窗口的边框和默认的标题栏给去掉,让Cozy看起来更像一个平板应用. 在主窗口的属性里,修改下列两个属性: 效果一目了然: 2. ...
- el-popover 的显示或隐藏,要在拿到真实dom之后再做控制
el-popover 的显示或隐藏,要在拿到真实dom之后再做控制
- 【java】【多线程】等待开启的多个线程都执行完成,再做事情,怎么实现
今天在controller中写一个接口用来测试模拟多个请求同时到达 下订单的情况, 怎么能有效保证高并发下的库存和销量的一致性呢?[具体实现方法:https://www.cnblogs.com/sxd ...
- Spark在处理数据的时候,会将数据都加载到内存再做处理吗?
对于Spark的初学者,往往会有一个疑问:Spark(如SparkRDD.SparkSQL)在处理数据的时候,会将数据都加载到内存再做处理吗? 很显然,答案是否定的! 对该问题产生疑问的根源还是对Sp ...
随机推荐
- Eclipse鼠标点击变量高亮显示时好时坏的BUG
Eclipse有一个BUG,就是鼠标点击某个变量会高亮显示所有这个变量 会有时高亮有时不高亮,修复这个BUG就是替换Eclipse 安装目录plugins目录下的org.eclipse.e4.ui.w ...
- xen 配置vm 跟随xen server一起启动
查看Xen Server 信息 (1)查看pool信息 [root@xenserver-243 ~]# xe pool-list uuid ( RO) : e29037aa-0dca-f95a-193 ...
- IDEA中设置注释模板的方法
IDEA中设置注释模板主要分为两个部分,分别是创建java文件时类的注释和方法的注释. 这里为大家详细介绍一下方法,按MyEclipse的风格设置(MyEclipse的请看:MyEclipse中设置注 ...
- AES加密【转】
. 此时就一定要使用如下代码步骤 : 1.SecureRandom的key定下来. SecureRandom 实现完全隨操作系统本身的內部狀態,除非調用方在調用 getInstance 方法之後又 ...
- JavaScript 从入门到放弃(一)事件委托和使用innerHTML添加元素
一.使用事件委托 一个简单的需求,比如想给ul下面的li加上点击事件,点击哪个li,就显示那个li的innerHTML.这个貌似很简单!代码如下! <!DOCTYPE html> < ...
- python -- 异步IO 协程
python 3.4 >>> import asyncio >>> from datetime import datetime >>> @asyn ...
- centos文件与权限
切换目录 cd:切换目录. 当我们需要进入到别的目录的时候,就需要使用到cd这个命令. ‘ cd这个命令主要有以下几种使用方式; cd [~]:进入当前用户的家目录,比如我是fuwh这个用户登陆的,则 ...
- DotNetBar 控件设置空内容时显示内容
可以通过修改所有关于Watermark时的设置.
- Database学习 - mysql 数据库 事务操作
事务 事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功. 数据库开启事务命令: start transaction 开启事务 rollback 回滚事务,即撤销指定的 ...
- OKVIS 代码框架
1. okvis_app_synchronous.cpp 在此文件中 okvis 对象为 okvis_estimator,是类 okvis::ThreadedKFVio 的实例化对象. 数据输入接口是 ...