P4198 楼房重建

题目链接

https://www.luogu.org/problemnew/show/P4198

题目描述

小A的楼房外有一大片施工工地,工地上有N栋待建的楼房。每天,这片工地上的房子拆了又建、建了又拆。他经常无聊地看着窗外发呆,数自己能够看到多少栋房子。

为了简化问题,我们考虑这些事件发生在一个二维平面上。小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段表示,其中Hi为第i栋楼房的高度。如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的。

施工队的建造总共进行了M天。初始时,所有楼房都还没有开始建造,它们的高度均为0。在第i天,建筑队将会将横坐标为Xi的房屋的高度变为Yi(高度可以比原来大—修建,也可以比原来小—拆除,甚至可以保持不变—建筑队这天什么事也没做)。请你帮小A数数每天在建筑队完工之后,他能看到多少栋楼房?

输入输出格式

输入格式:

第一行两个正整数N,M

接下来M行,每行两个正整数Xi,Yi

输出格式:

M行,第i行一个整数表示第i天过后小A能看到的楼房有多少栋

输入输出样例

输入样例#1:

3 4

2 4

3 6

1 1000000000

1 1

输出样例#1:

1

1

1

2

说明

对于所有的数据\(1<=Xi<=N,1<=Yi<=10^9\)

\(N,M<=100000\)

题解

线段树维护,记录一个max,sum即可,代码很短,但是有个点需要注意,我在代码相应位置标记了。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 100050
int n,m;
struct Tree{int l,r,sum; double max;}tr[N<<2];
template<typename T>void read(T&x)
{
ll k=0; char c=getchar();
x=0;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit(0);
while(isdigit(c))x=x*10+c-'0',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
int get_sum(int x,double tt)
{
if (tr[x].max<=tt)return 0;
if (tr[x].l==tr[x].r)return tr[x].sum;
Tree &a=tr[x<<1],&b=tr[x<<1|1];
if (tt>=a.max)return get_sum(x<<1|1,tt);
else return get_sum(x<<1,tt)+tr[x].sum-a.sum;//这里不能写成 get_sum(x<<1,tt)+b.sum;
}
void push_up(int x)
{
Tree &a=tr[x<<1],&b=tr[x<<1|1];
tr[x].max=max(a.max,b.max);
tr[x].sum=a.sum+get_sum(x<<1|1,a.max);
}
void bt(int x,int l,int r)
{
tr[x].l=l; tr[x].r=r;
if (l==r)return;
int mid=(l+r)>>1;
bt(x<<1,l,mid);
bt(x<<1|1,mid+1,r);
}
void update(int x,int p,double tt)
{
if (tr[x].l==tr[x].r)
{
tr[x].max=tt;
tr[x].sum=1;
return;
}
int mid=(tr[x].l+tr[x].r)>>1;
if (p<=mid)update(x<<1,p,tt);
else update(x<<1|1,p,tt);
push_up(x);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
read(n); read(m);
bt(1,1,n);
for(int i=1;i<=m;i++)
{
int x;double tt;
read(x); read(tt);tt=tt/x;
update(1,x,tt);
printf("%d\n",tr[1].sum);
}
}
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 100050
int n,m;
struct Tree{int l,r,sum; double max;}tr[N<<2];
template<typename T>void read(T&x)
{
ll k=0; char c=getchar();
x=0;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit(0);
while(isdigit(c))x=x*10+c-'0',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
int get_sum(int x,double tt)
{
if (tr[x].max<=tt)return 0;
if (tr[x].l==tr[x].r)return tr[x].sum;
Tree &a=tr[x<<1],&b=tr[x<<1|1];
if (tt>=a.max)return get_sum(x<<1|1,tt);
else return get_sum(x<<1,tt)+tr[x].sum-a.sum;//这里不能写成 get_sum(x<<1,tt)+b.sum;
}
void push_up(int x)
{
Tree &a=tr[x<<1],&b=tr[x<<1|1];
tr[x].max=max(a.max,b.max);
tr[x].sum=a.sum+get_sum(x<<1|1,a.max);
}
void bt(int x,int l,int r)
{
tr[x].l=l; tr[x].r=r;
if (l==r)return;
int mid=(l+r)>>1;
bt(x<<1,l,mid);
bt(x<<1|1,mid+1,r);
}
void update(int x,int p,double tt)
{
if (tr[x].l==tr[x].r)
{
tr[x].max=tt;
tr[x].sum=1;
return;
}
int mid=(tr[x].l+tr[x].r)>>1;
if (p<=mid)update(x<<1,p,tt);
else update(x<<1|1,p,tt);
push_up(x);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
read(n); read(m);
bt(1,1,n);
for(int i=1;i<=m;i++)
{
int x;double tt;
read(x); read(tt);tt=tt/x;
update(1,x,tt);
printf("%d\n",tr[1].sum);
}
}

洛谷 P4198 楼房重建 线段树维护单调栈的更多相关文章

  1. 洛谷P4198 楼房重建(线段树)

    题意 题目链接 Sol 别问我为什么发两遍 就是为了骗访问量 这个题的线段树做法,,妙的很 首先一个显然的结论:位置\(i\)能被看到当且仅当\(\frac{H_k}{k} < \frac{H_ ...

  2. 洛谷P4198 楼房重建 (分块)

    洛谷P4198 楼房重建 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题, ...

  3. [CSP-S模拟测试]:陶陶摘苹果(线段树维护单调栈)

    题目传送门(内部题116) 输入格式 第一行两个整数$n,m$,如题 第二行有$n$个整数表示$h_1-h_n(1\leqslant h_i\leqslant 10^9)$ 接下来有$m$行,每行两个 ...

  4. [Luogu P4198]楼房重建(线段树)

    题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个 ...

  5. 洛谷 P4198 楼房重建

    思路 此题可转化为以下模型 给定序列\(a[1...n]\),支持单点修改,每次求区间单调栈大小 \(n,Q\le 10^5\) 区间单调栈是什么呢?对于一个区间,建立一个栈,首先将第一个元素入栈,从 ...

  6. 洛谷P4198 楼房重建 单调栈+线段树

    正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...

  7. luogu P4198 楼房重建——线段树

    题目大意: 小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段表示,其中Hi为第i栋楼房的高度.如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没有与之前的线 ...

  8. [BZOJ 2957]楼房重建(THU2013集训)(线段树维护单调栈)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2957 分析: 根据题意,就是比较斜率大小 只看一段区间的话,那么这段区间能看见的楼房数量就是这 ...

  9. 洛谷 P4198 楼房重建 题解

    题面 首先你要知道题问的是什么:使用一种数据结构,动态地维护以1为起点地最长上升子序列(把楼房的高度转化成斜率地序列)的长度: 怎么做?线段树! 我们在线段树上维护两个东西:1.这个区间内斜率的最大值 ...

随机推荐

  1. c实现循环链表

    解决约瑟夫环问题核心步骤: 1.建立具有n个节点.无头的循环链表 2.确定第一个报数人的位置 3.不断从链表中删除链节点,直到链表为空 #include <iostream> #inclu ...

  2. Irrlicht引擎剖析一

    代码风格:  1.接口以I开头,实现以C开头,保存数据的结构体以S开头  2.函数名以小写字母开头,变量以大字母开头  3.接口的公共函数,其参数大部分给了默认值  4.采用名字空间    名字空间i ...

  3. pom.xml报错 : Missing artifact org.apache.shiro:shiro-spring:bundle:1.2.5

    添加有<type>bundle</type>标签的依赖时,都会报这个错. 需要在<build/><plugins/>里面追加标签 <plugin& ...

  4. 普转提——有趣的数,欢乐ABC,打游戏

    有趣的数——构造符合条件的数 给你一个区间,问有多少个数符合每一位中,只有一个数字和其他数字不同,也就是其他数字都相同,有且只有一个异类: 数据范围是1e16: 因为只考虑数量而不用管大小: 只要0到 ...

  5. 1937:【06NOIP普及组】数列

    woc 太捞了简直捞的一匹 我居然会写博客 反正呀没有人看 随便写写喽

  6. jenkins之docker安装

    此方法安装还存在两个问题1.构建node程序:2.时区问题(在docker run 设置环境变量是否能解决没有试过) 不建议用此方法安装,查看我的其他安装方式 搬运官网步骤,稍微改动. 1.安装doc ...

  7. centos7的网络配置参考

    <鸟哥的Linux私房菜>中的相关介绍和配置:http://linux.vbird.org/linux_basic/0610hardware.php 修改链接(connection)的名字 ...

  8. Linux 文件存在程序找不到文件

    1. 编码格式 程序运行时的编码格式和传输到程序中参数的编码格式是否一致,可以在程序中打印日志进行验证: 2. 转义符 文件路径中存在转义符 3. 运行程序的用户身份 不同用户运行程序也可能导致编码格 ...

  9. geth run

    geth --networkid 1201 --rpc --rpcapi eth,net,web3,personal,admin,miner --rpccorsdomain "*" ...

  10. How to Publish a NuGet Package

    How to Publish a NuGet Package Command line To push packages to nuget.org you must use nuget.exe v4. ...