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 ...
随机推荐
- spring @Transactional注解参数详解
事物注解方式: @Transactional 当标于类前时, 标示类中所有方法都进行事物处理 , 例子: @Transactional public class TestServiceBean imp ...
- 化工pdf下载
Python爬虫视频教程零基础小白到scrapy爬虫高手-轻松入门 https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.482434a6E ...
- GBDT用于分类问题
一.简介 GBDT在传统机器学习算法里面是对真实分布拟合的最好的几种算法之一,在前几年深度学习还没有大行其道之前,gbdt在各种竞赛是大放异彩.原因大概有几个 一:效果确实挺不错. 二:既可以用于分类 ...
- mysql优化问题汇总
sql优化-->分区-->分表-->垂直分库-->水平分库-->读写分离 分区 关于分区的博客推荐这个:https://blog.csdn.net/youzhouliu/ ...
- <!--more-->搭建的博客设置主页内容高度
用 markdown写文章时插入<!--more-->,文章会自动从插入的位置截断,也就是说在博客中只显示<!--more-->之前的内容,点击阅读全文之后会显示所有内容.
- Linux记录-TCP状态以及(TIME_WAIT/CLOSE_WAIT)分析(转载)
1.TCP握手定理 2.TCP状态 l CLOSED:初始状态,表示TCP连接是“关闭着的”或“未打开的”. l LISTEN :表示服务器端的某个SOCKET处于监听状态,可以接受客户端的连接. ...
- cetus系列~安装和基本配置
cetus系列一 安装 1 安装软件环境 yum install cmake gcc glib2-devel flex mysql-devel gperftools-libs bison f ...
- UML和模式应用4:初始阶段(5)--用例编写的准则
1.前言 本文主要介绍用例编写时所遵循的几条基本准则. 2.用例编写的准则 2.1 以本质的风格编写用例 如系统认证,而不要说 需要输入ID进行认证等 2.2 编写简洁的用例 如系统认证,不要说 这个 ...
- xpath与nodejs解析xml
测试xpath的工具 http://www.freeformatter.com/xpath-tester.html#ad-output http://www.xpathtester.com/test ...
- #ifndef详解
#ifndef 是"if not defined"的简写,是预处理功能(宏定义.文件包含.条件编译)当中的条件编译,可以根据是否已经定义了一个变量来进行分支选择,其作用是: 1.防 ...