【洛谷】P4198 楼房重建
题解
我们转而维护每个点的斜率,显然一个楼房能被看见它就是一个前缀最大值,斜率比较为了节约精度可以用向量替代
我们每个区间维护被看到的楼房的个数,和楼房的最大值,叶子节点在有楼房时,值为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 楼房重建的更多相关文章
- 洛谷P4198 楼房重建 (分块)
洛谷P4198 楼房重建 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题, ...
- 洛谷 P4198 楼房重建 题解
题面 首先你要知道题问的是什么:使用一种数据结构,动态地维护以1为起点地最长上升子序列(把楼房的高度转化成斜率地序列)的长度: 怎么做?线段树! 我们在线段树上维护两个东西:1.这个区间内斜率的最大值 ...
- 洛谷P4198 楼房重建 单调栈+线段树
正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...
- 洛谷P4198 楼房重建(线段树)
题意 题目链接 Sol 别问我为什么发两遍 就是为了骗访问量 这个题的线段树做法,,妙的很 首先一个显然的结论:位置\(i\)能被看到当且仅当\(\frac{H_k}{k} < \frac{H_ ...
- 洛谷P4198 楼房重建
题意:给定序列,每次修改一个值,求前缀最大值的个数. 解:线段树经典应用. 每个节点维护最大值和该区间前缀最大值个数. 发现我们不用下传标记,只需要合并区间. 需要实现一个函数int ask([l r ...
- 洛谷 P4198 楼房重建
思路 此题可转化为以下模型 给定序列\(a[1...n]\),支持单点修改,每次求区间单调栈大小 \(n,Q\le 10^5\) 区间单调栈是什么呢?对于一个区间,建立一个栈,首先将第一个元素入栈,从 ...
- 洛谷 P4198 楼房重建 线段树维护单调栈
P4198 楼房重建 题目链接 https://www.luogu.org/problemnew/show/P4198 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上 ...
- P4198 楼房重建
P4198 楼房重建 集中写博客= = 首先把高度变成斜率 然后就比较玄学了,首先用线段树维护一个区间的斜率最大值,和只看这个区间时能看见的楼房个数ans 然后更新时先更新max,再处理神奇的ans ...
- 洛谷P1119-灾后重建-floyd算法
洛谷P1119-灾后重建 题目描述 给出\(B\)地区的村庄数NN,村庄编号从\(0\)到\(N-1\),和所有\(M\)条公路的长度,公路是双向的. 给出第\(i\)个村庄重建完成的时间\(t_i\ ...
- 洛谷 P3905 道路重建
题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B ...
随机推荐
- Spring Shell介绍
最近开发中在下遇到了spring-shell开发工具的项目,现在整理了相关文章,以供大家学习 本博客相关的文章均是在Spring Shell 1.2.0的基础上建立 Spring Shell介绍 ...
- 解题:HEOI 2012 朋友圈
题面 因为$A$中只有奇偶性不同的人才能做朋友,所以A中只可能出0/1/2个人,分类讨论 然后$B$中求最大团,转成补图后正好是个二分图(不然就不用做了),求最大点独立集=总点数-最大匹配 我洛谷上交 ...
- c++并发编程之互斥锁(mutex)的使用方法
1. 多个线程访问同一资源时,为了保证数据的一致性,最简单的方式就是使用 mutex(互斥锁). 引用 cppreference 的介绍: The mutex class is a synchroni ...
- js判断是否为空
http://dushanggaolou.iteye.com/blog/1293803 1.<input type="hidden" id="key" n ...
- 数组初始化 memset fill
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #in ...
- spring注入时报错::No qualifying bean of type 'xxx.xxMapper'
做一个小项目,因为有 baseService,所以偷懒就没有写单独的每个xxService接口,直接写的xxServiceImpl,结果在service实现类中注入Mapper的时候,用的 @Auto ...
- 集合框架基础知识-----java基础知识
Java集合框架 :接口:Collection.List .Set. Map:实现类:ArrayList.LinkedList.Vector.HashSet.TreeSet.HashMap.HashT ...
- 菜单栏--Dom选择器
制作一个左侧菜单栏,包含菜单目录和内容 点击菜单栏才会展示内容,否则隐藏内容 二.事例 2.1 菜单栏基本样式 <body> <div style="height: 48p ...
- Hadoop生态圈-Kafka常用命令总结
Hadoop生态圈-Kafka常用命令总结 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.管理Kafka服务的命令 1>.开启kafka服务 [yinzhengjie@s ...
- 网络获取json数据并解析
1.升级流程分析