2000 楼房重建 2012年
时间限制: 1 s
空间限制: 256000 KB
题目等级 : 大师 Master
查看运行结果
题目描述 Description
小A的楼房外有一大片施工工地,工地上有N栋待建的楼房。每天,这片工地上的房子拆了又建、建了又拆。他经常无聊地看着窗外发呆,数自己能够看到多少栋房子。 为了简化问题,我们考虑这些事件发生在一个二维平面上。小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段表示,其中Hi为第i栋楼房的高度。如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的。 施工队的建造总共进行了M天。初始时,所有楼房都还没有开始建造,它们的高度均为0。在第i天,建筑队将会将横坐标为Xi的房屋的高度变为Yi(高度可以比原来大---修建,也可以比原来小---拆除,甚至可以保持不变---建筑队这天什么事也没做)。请你帮小A数数每天在建筑队完工之后,他能看到多少栋楼房?
输入描述 Input Description
第一行两个正整数N,M 接下来M行,每行两个正整数Xi,Yi
输出描述 Output Description
M行,第i行一个整数表示第i天过后小A能看到的楼房有多少栋
样例输入 Sample Input
3 4 2 4 3 6 1 1000000000 1 1
样例输出 Sample Output
1 1 1 2
数据范围及提示 Data Size & Hint
测试点 |
N,M |
---|---|
1 |
<=100 |
2 |
<=5000 |
3 |
<=50000 |
4 |
<=100000 |
5 |
<=30000 |
6 |
<=50000 |
7 |
<=70000 |
8 |
<=80000 |
9 |
<=90000 |
10 |
<=100000 |
其他条件:测试点1~4:建筑队每天等概率随机选择一栋房屋将其改造成1~109内的等概率随机高度。测试点5~10:无。
来源:中国国家队清华集训 2012-2013 第一天
分类标签 Tags 点此展开
每个节点维护区间内可见数目以及最大斜率. 两个区间合并时, 左边的可见数目不变, 右边的可见数目不能直接得 到, 考虑递归查询: 设左区间最大斜率为 k. 我们要对每个节点计算如果在它左边加一 个斜率为 k 的楼房, 它的可见数目是多少.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<bitset>
#define ls k<<1
#define rs k<<1|1
using namespace std;
const int MAXN=1000001;
inline void read(int &n)
{
char c='+';int x=0;bool flag=0;
while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;}
while(c>='0'&&c<='9'){x=x*10+(c-48);c=getchar();}
n=flag==1?-x:x;
}
struct node
{
int l,r,num;
double maxrake;
}tree[MAXN<<2];
int n,m;
int calc(int k,double val)
{
if(tree[k].l==tree[k].r)
return tree[k].maxrake>val;// 能看见
if(tree[ls].maxrake<=val)
return calc(rs,val);// 最高的都比它小,直接计算右边
return tree[k].num-tree[ls].num+calc(ls,val);//
}
void update(int k)
{
tree[k].maxrake=max(tree[ls].maxrake,tree[rs].maxrake);
tree[k].num=tree[ls].num+calc(rs,tree[ls].maxrake);
}
void build_tree(int ll,int rr,int k)
{
tree[k].l=ll;tree[k].r=rr;
if(ll==rr)
return ;
int mid=(ll+rr)>>1;
build_tree(ll,mid,ls);
build_tree(mid+1,rr,rs);
}
void change(int k,int pos,double val)
{
if(tree[k].l==tree[k].r)
{
tree[k].num=1;
tree[k].maxrake=val;
return ;
}
int mid=(tree[k].l+tree[k].r)>>1;
if(pos<=mid) change(ls,pos,val);
else change(rs,pos,val);
update(k);
}
int main()
{
freopen("hh.in","r",stdin);
read(n);read(m);
build_tree(1,n,1);
for(int i=1;i<=m;i++)
{
int pos,h;
read(pos);read(h);
change(1,pos,(double)h/pos);
printf("%dn",tree[1].num);
}
return 0;
}
- 自己做的一个小程序 可采集、导出、模板、配置
- 分布式消息队列 RocketMQ 源码分析 —— Message 拉取与消费(上)
- .NET反射、委托技术与设计模式
- 我最常用的Intellij IDEA快捷键
- 用Js控制TextBox不能复制粘贴
- 漫画:什么是单例模式?(整合版)
- 保护连接字符串
- IntelliJ IDEA 复杂的重构技巧(二)
- Spring Boot中使用Flyway来管理数据库版本
- 缓存穿透、缓存并发、热点缓存之最佳招式
- 【译】Spring 官方教程:使用 Restdocs 创建 API 文档
- c#中设置快捷键
- 程序员你为什么这么累【续】:编码习惯之工具类规范
- IntelliJ IDEA 复杂的重构技巧
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- (15)Shell概述及脚本执行方式
- jvm线上内存问题排查
- (18)Bash输入输出重定向
- RPC 和 REST还有RESTFul到底是个什么玩意?
- 线程和线程池的几个状态值
- 阿里代码规约为什么不让使用Executors包装好线程池呢?
- Groovy、热部署和热加载(自定义类加载器)及spring loaded 部分源码分析
- Centos在线迁移到腾讯云cvm
- ClickHouse源码导读:网络IO
- 手把手教你:将ClickHouse集群迁至云上
- 直播中台iLiveSDK终端框架演变之路
- ClickHouse 数据导入实战:Kafka 篇
- pipeAsyncFunctions
- 【python-leetcode287-循环排序】寻找重复的数
- 聊聊claudb的list command