洛谷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

Solution

我们发现能看见的楼房的个数,就是这些楼房的斜率的最长上升子序列的长度,可以线段树维护,也可以分块,但是分块要慢得多

博主在这里讲一下分块的做法,线段树以后再补?

设有两个点a,b,高度分别为h[a],h[b],如果a不会被b阻挡,必有\(\frac{h[a]}{a}>=\frac{h[b]}{b}\),化为乘法形式为\(h[a]\times b>=h[b]\times a\),特别的,对于原点,我们特判一下,h[a]是不是大于0就可以了

对于修改,我们暴力更新本块内元素信息,每次清零,重新维护一个块内最长上升子序列的长度,时间复杂度\(O(\sqrt n)\)

对于查询,设last为上一个满足条件的块的末尾节点,我们每次从块1开始,一直到最后一块,在块内二分查找(因为是最长上升子序列,所以满足单调性)与last相比刚刚满足条件的点,那么从这个点开始一直到块末都是合法的序列,把答案加上这一段区间的长度,然后把last更新为本块末尾,继续上述操作

时间复杂度\(O(\sqrt n)\)

然而这样是会T的,我们把块的大小改为\(\sqrt {\frac{n\times log(n)}{2}}\)会有奇效,但是记得数组大小也要相应更改

Code

#include<bits/stdc++.h>
#define rg register
#define lol long long
#define il extern inline
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)
#define in(i) (i=read())
using namespace std;
const lol N=1e5+10;
int read() {
int ans=0,f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0',i=getchar();
return ans*f;
} int n,m,blo,h[N],pos[N];
struct Stack {
int s[N],top;
}t[330];
il bool check(lol a,lol b) {
if(!b) return h[a]>0;
return (lol)(h[a]*b)>(lol)(h[b]*a);
} void print(int x) {
if(x>9) print(x/10);
putchar(x%10+'0');
} int main() {
in(n),in(m); blo=sqrt(n*log(n)/2);
for(rg int i=1;i<=n;i++) pos[i]=(i-1)/blo+1;
while(m--) {
int x,ans=0; in(x),in(h[x]);
rg int l=(pos[x]-1)*blo+1,r=Min(n,pos[x]*blo);
t[pos[x]].top=0;
for(rg int i=l;i<=r;i++)
if(check(i,t[pos[x]].s[t[pos[x]].top]))
t[pos[x]].s[++t[pos[x]].top]=i;//用一个栈来维护
for(rg int i=1,last=0;i<=pos[n];i++) {
rg int AQ=0; l=1,r=t[i].top;
while(l<=r) {
int mid=l+r>>1;
if(check(t[i].s[mid],last)) AQ=mid,r=mid-1;
else l=mid+1;
}
if(AQ) last=t[i].s[t[i].top],ans+=t[i].top-AQ+1;
}print(ans),putchar('\n');
}
}

洛谷P4198 楼房重建 (分块)的更多相关文章

  1. 洛谷 P4198 楼房重建 题解

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

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

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

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

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

  4. 洛谷P4198 楼房重建

    题意:给定序列,每次修改一个值,求前缀最大值的个数. 解:线段树经典应用. 每个节点维护最大值和该区间前缀最大值个数. 发现我们不用下传标记,只需要合并区间. 需要实现一个函数int ask([l r ...

  5. 洛谷 P4198 楼房重建

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

  6. Luogu P4198 楼房重建 分块 or 线段树

    思路:分块 提交:2次(第一次的求解有问题) 题解: 设块长为$T$,我们开$N/T$个单调栈,维护每一块的上升斜率. 修改时暴力重构整个块,$O(T)$ 求解时记录一个最大斜率$lst$,然后块内二 ...

  7. 洛谷 P4198 楼房重建 线段树维护单调栈

    P4198 楼房重建 题目链接 https://www.luogu.org/problemnew/show/P4198 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上 ...

  8. P4198 楼房重建

    P4198 楼房重建 集中写博客= = 首先把高度变成斜率 然后就比较玄学了,首先用线段树维护一个区间的斜率最大值,和只看这个区间时能看见的楼房个数ans 然后更新时先更新max,再处理神奇的ans ...

  9. 洛谷P1119-灾后重建-floyd算法

    洛谷P1119-灾后重建 题目描述 给出\(B\)地区的村庄数NN,村庄编号从\(0\)到\(N-1\),和所有\(M\)条公路的长度,公路是双向的. 给出第\(i\)个村庄重建完成的时间\(t_i\ ...

随机推荐

  1. 375. Clone Binary Tree【LintCode java】

    Description For the given binary tree, return a deep copy of it. Example Given a binary tree: 1 / \ ...

  2. 关于Filter中ServletRequest强转HttpServletRequest问题

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOE ...

  3. ArcFaceDemo 第二版【C#】——视频人脸识别

    啥话不说,不用跪求,直接给下载地址:http://common.tenzont.com/comdll/arcface2demo.zip(话说附件的大小不限制,还是说我的文件太大,实际上确实有点大,60 ...

  4. 聊聊、dubbo 找不到 dubbo.xsd 报错

    平常在用 Dubbo 的时候,创建 xml 会提示 http://code.alibabatech.com/schema/dubbo/dubbo.xsd 找不到. 大家可以去 https://gith ...

  5. opencv打开视频文件出错

    使用C#调用mingw的so文件,在C++端使用opencv打开视频.这样的项目完成过了一个,第二次做的时候,发现opencv打开视频文件出错. 首先怀疑是opencv的opencv_ffmpeg24 ...

  6. css3美化radio样式

    .magic-radio{ position: absolute; display: none; } .magic-radio + label { position: relative; displa ...

  7. StrBlobPtr类——weak_ptr访问vector元素

    #include <iostream> #include <memory> #include <string> #include <initializer_l ...

  8. Internet History

    Alan Turing and Bletchley Park Top secret breaking effort(二战破译希特勒密码) 10,000 people at the peak(team ...

  9. RHEL 6.4(i386)安装MySQL 5.6的方法

  10. (转)NEST.net Client For Elasticsearch简单应用

    由于最近的一个项目中的搜索部分要用到 Elasticsearch 来实现搜索功能,苦于英文差及该方面的系统性资料不好找,在实现时碰到了不少问题,现把整个处理过程的代码分享下,给同样摸索的人一些借鉴,同 ...