题解

我们转而维护每个点的斜率,显然一个楼房能被看见它就是一个前缀最大值,斜率比较为了节约精度可以用向量替代

我们每个区间维护被看到的楼房的个数,和楼房的最大值,叶子节点在有楼房时,值为1

那么考虑合并两个区间,左节点的所有能被看到的楼房还是能被看到,右边节点能看到的楼房的斜率需要大于左边节点所需要的斜率最大值

为了找到这些我们去右节点的左右区间去找

如果这个值\(P\)大于等于区间左边的最大值,那么这个值要在右边找

如果小于的话,加上右边的大小,即\(tr[u].cnt - tr[u << 1].cnt\),然后递归到左边处理

复杂度\(O(n \log^2 n)\)

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
struct Point {
int64 x,y;
Point(int64 _x = 0,int64 _y = 0) {
x = _x;y = _y;
}
friend Point operator + (const Point &a,const Point &b) {
return Point(a.x + b.x,a.y + b.y);
}
friend Point operator - (const Point &a,const Point &b) {
return Point(a.x - b.x,a.y - b.y);
}
friend int64 operator * (const Point &a,const Point &b) {
return a.x * b.y - a.y * b.x;
}
friend bool operator < (const Point &a,const Point &b) {
return a * b > 0;
}
friend bool operator > (const Point &a,const Point &b) {
return a * b < 0;
}
friend bool operator == (const Point &a,const Point &b) {
return a * b == 0;
}
friend bool operator >= (const Point &a,const Point &b) {
return a > b || a == b;
}
friend bool operator <= (const Point &a,const Point &b) {
return a < b || a == b;
}
};
struct node {
int L,R,cnt;Point P;
}tr[MAXN * 4];
int N,M; void build(int u,int l,int r) {
tr[u].L = l;tr[u].R = r;tr[u].cnt = 0;
tr[u].P = Point(r,0);
if(l == r) return;
int mid = (l + r) >> 1;
build(u << 1,l,mid);
build(u << 1 | 1,mid + 1,r);
}
int Calc(int u,Point P) {
if(tr[u].L == tr[u].R) return tr[u].P > P;
if(P >= tr[u << 1].P) {
return Calc(u << 1 | 1,P);
}
else {
return Calc(u << 1,P) + tr[u].cnt - tr[u << 1].cnt;
}
}
void Change(int u,int pos,int y) {
if(tr[u].L == tr[u].R) {
tr[u].P = Point(pos,y);
if(!y) tr[u].cnt = 0;
else tr[u].cnt = 1;
return;
}
int mid = (tr[u].L + tr[u].R) >> 1;
if(pos <= mid) Change(u << 1,pos,y);
else Change(u << 1 | 1,pos,y);
tr[u].P = max(tr[u << 1].P,tr[u << 1 | 1].P);
tr[u].cnt = tr[u << 1].cnt + Calc(u << 1 | 1,tr[u << 1].P);
}
void Solve() {
read(N);read(M);
build(1,1,N);
int x,y;
for(int i = 1 ; i <= M ; ++i) {
read(x);read(y);
Change(1,x,y);
out(tr[1].cnt);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}

【洛谷】P4198 楼房重建的更多相关文章

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

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

  2. 洛谷 P4198 楼房重建 题解

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

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

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

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

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

  5. 洛谷P4198 楼房重建

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

  6. 洛谷 P4198 楼房重建

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

  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\ ...

  10. 洛谷 P3905 道路重建

    题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B ...

随机推荐

  1. MT【181】横穿四象限

    设函数$f(x)=\dfrac{1}{x-a}-\dfrac{\lambda}{x-2}$,其中$a,\lambda\in R$记$A_1=\{(x,y)|x>0,y>0\},A_2=\{ ...

  2. 「TJOI / HEOI2016」字符串

    「TJOI / HEOI2016」字符串 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为 \(n\) 的字符串 \(s\),和 ...

  3. 获取androdmanifest里面的meta-data

    /* * Copyright 2017 JessYan * * Licensed under the Apache License, Version 2.0 (the "License&qu ...

  4. bzoj4542: [Hnoi2016]大数(莫队)

    这题...离散化...$N$和$n$搞错了...查了$2h$...QAQ 考虑$s[l...r]$,可以由两个后缀$suf[l]-suf[r+1]$得到$s[l...r]$代表的数乘$10^k$得到的 ...

  5. oracle递归查询(查询条件ID下得所有子集)

    一.CREATE TABLE TBL_TEST ( ID    NUMBER, NAME  VARCHAR2(100 BYTE), PID   NUMBER                       ...

  6. Json对象和Json字符串的区别

    说白了,字符串都是带引号的. 尤其是在使用springmvc的时候,后台@RequestBody接受的是一个json格式的字符串,一定是一个字符串.  参考这个博客还可以: https://blog. ...

  7. solr与mysql数据同步的方案

    1.使用activeMQ http://blog.csdn.net/zhou2s_101216/article/details/77855413 2.通过配置实现定时同步 http://blog.cs ...

  8. python循环删除列表元素常见错误与正确方法

    python循环删除列表元素 觉得有用的话,欢迎一起讨论相互学习~Follow Me 常见错误 常见错误一:使用固定长度循环删除列表元素 # 使用固定长度循环pop方法删除列表元素 num_list_ ...

  9. pytho部分命令

    python --version查看版本号 pip install XXX 安装模块 pip uninstall XXX 卸载模块

  10. 在Emacs中启用Fcitx输入法

    安装fcitx输入法,在 ~/.xinitrc文件中添加如下内容 (我用startx启动图形环境,所以在~/.xinitrc中配置X会话) export LC_CTYPE="zh_CN.UT ...