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使用总结(不定时更新)
1.安装activiti插件 (1)在线下载 点击Add输入Location:http://activiti.org/designer/update/ Name:Activiti (2)本地安装 ...
- Nginx+Swoole服务器配置
nginx 配置 server { listen 80; server_name www.swoole.com; root /data/wwwroot/www.swoole.com; location ...
- nginx安装ngx_lua_waf防护
ngx_lua_waf基于ngx_lua的web应用防火墙,使用起来简单,高性能和轻量级. ♦防止sql注入,本地包含,部分溢出,fuzzing测试,xss,SSRF等web攻击♦防止svn/备份之类 ...
- js通用绑定事件函数
- python 内建函数专题
all 用来控制 import , 甚至可以改变 _private 为 public enter , exit 用于上下文管理器 iter 用于迭代器 repr 给计算机读, str ==> s ...
- Spring XML配置里的Bean自动装配
Spring自动装配 这段是我们之前编写的代码,代码中我们使用了P命名空间 并且使用手动装配的方式将car <bean id="address" class="cn ...
- JavaScript之表格操作(二)创建表格病填充表格数据
//创建表格 var tableOptions = { way: "insertBefore", //insertBefore,append positionId: "d ...
- adb环境变量配置
针对win10系统: 搜索“高级系统设置”,点击“环境变量”按钮: 找到“path”双击: 双击“path”,在弹出的环境变量列表中新建,填入adb的文件路径 检查配置是否成功,运行命令adb,出现如 ...
- script标签中type为"text/x-template"或"text/html"
写过一点前端的都会碰到需要使用JS字符串拼接HTML元素然后append到页面DOM树上的情况,一般的写法都是使用+号以字符串的形式拼接,如果是短点的还好,如果很长很长的话就会拼接到令人崩溃了. 比如 ...
- spring整合ehcache2.5.2缓存异常-- net.sf.ehcache.CacheException
报错如下: The source of the existing CacheManager is: DefaultConfigurationSource [ ehcache.xml or ehcach ...