扫描线+区间更新

题解

/*
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扫描线好题,回头再做的更多相关文章

  1. cf276E 两棵线段树分别维护dfs序和bfs序,好题回头再做

    搞了一晚上,错了,以后回头再来看 /* 对于每次更新,先处理其儿子方向,再处理其父亲方向 处理父亲方向时无法达到根,那么直接更新 如果能达到根,那么到兄弟链中去更新,使用bfs序 最后,查询结点v的结 ...

  2. poj2464扫描线好题,树状数组解法

    用树状数组解比线段树快了好多,难度也下降许多 分别用两个树状数组维护当前扫描线左侧和右侧的点,离散化y轴即可 #include<iostream> #include<cstring& ...

  3. uva12436 回头再做一次

    线段树维护等差数列,结点维护首项+公差即可 #include <cstdio> #include <cstring> #include <algorithm> us ...

  4. hdu4942线段树模拟rotate操作+中序遍历 回头再做

    很有意思的题目,详细题解看这里 https://blog.csdn.net/qian99/article/details/38536559 自己的代码不知道哪里出了点问题 /* rotate操作不会改 ...

  5. Go: LeetCode简单题,简单做(sort.Search)

    前言 正值端午佳节,LeetCode也很懂.这两天都是简单题,早点做完去包粽子. 故事从一道简单题说起 第一个错误的版本 简单题 你是产品经理,目前正在带领一个团队开发新的产品.不幸的是,你的产品的最 ...

  6. CozyRSS开发记录3-标题栏再加强

    CozyRSS开发记录3-标题栏再加强 1.更精炼的标题栏 接下来,我们把窗口的边框和默认的标题栏给去掉,让Cozy看起来更像一个平板应用. 在主窗口的属性里,修改下列两个属性: 效果一目了然: 2. ...

  7. el-popover 的显示或隐藏,要在拿到真实dom之后再做控制

    el-popover 的显示或隐藏,要在拿到真实dom之后再做控制

  8. 【java】【多线程】等待开启的多个线程都执行完成,再做事情,怎么实现

    今天在controller中写一个接口用来测试模拟多个请求同时到达 下订单的情况, 怎么能有效保证高并发下的库存和销量的一致性呢?[具体实现方法:https://www.cnblogs.com/sxd ...

  9. Spark在处理数据的时候,会将数据都加载到内存再做处理吗?

    对于Spark的初学者,往往会有一个疑问:Spark(如SparkRDD.SparkSQL)在处理数据的时候,会将数据都加载到内存再做处理吗? 很显然,答案是否定的! 对该问题产生疑问的根源还是对Sp ...

随机推荐

  1. 网络编程基础【day09】:socket编程入门(一)

    本节内容 1.OSI七层模型 2.概述 3.关系图 4.代码逻辑图 5.socket概念 一.OSI七层模型 二.概述 socket通常也称作"套接字",用于描述IP地址和端口,是 ...

  2. Swift学习笔记9--错误控制

    1.Swift 中有4种处理错误的方式.你可以把函数抛出的错误传递给调用此函数的代码.用do-catch语句处理错误.将错误作为可选类型处理.或者断言此错误根本不会发生. 2.wift 中的错误处理并 ...

  3. centos7.5 python修复

    参考文章地址: 1.CentOS7修复python拯救yum: http://blog.51cto.com/welcomeweb/2132654 所有rpm包下载完成 wget http://mirr ...

  4. Java NIO 机制分析(一) Java IO的演进

    一.引言 Java1.4之前的早期版本,Java对I/O的支持并不完善,开发人员再开发高性能I/O程序的时候,会面临一些巨大的挑战和困难,主要有以下一些问题: (1)没有数据缓冲区,I/O性能存在问题 ...

  5. luogu P3978 [TJOI2015]概率论

    看着就是要打表找规律 使用以下代码 for(int i=3;i<=20;i++) { int a1=0,a2=0; for(int j=1;j<i;j++) { for(int k=0;k ...

  6. 洛谷4718【模板】Pollard-Rho算法

    传送门 Description: 给定T个数,分别求出它们的最大质因数 Solution: 其实大概框架是很容易想到的 对于一个数n 找到它的一个因数x 判断这个因数是不是质数 如果是质数就更新答案 ...

  7. 【通信】JDK中的URLConnection参数详解

    JDK中的URLConnection参数详解 来自:http://www.blogjava.net/supercrsky/articles/247449.html 针对JDK中的URLConnecti ...

  8. G - 楼房重建 (线段树)

    题目链接:https://cn.vjudge.net/contest/281960#problem/G 题目大意:中文问题 具体思路:首先每一个点的值可以用当前这个点的斜率来表示,每一次输入一个值,我 ...

  9. XMLHttpRequest: 网络错误 0x2f78,…00002f78

    常在河边走,怎能不湿脚,在web前端开发的过程中总是遇到很多关于IE的故事. 一个get请求,传了一个json对象,包含一串参数,在IE上就出现了这个问题:XMLHttpRequest: 网络错误 0 ...

  10. box-cox 转换

    box-cox 由于线性回归是基于正态分布的前提假设,所以对其进行统计分析时,需经过数据的转换,使得数据符合正态分布. Box 和 Cox在1964年提出的Box-Cox变换可使线性回归模型满足线性性 ...