每个楼房,还有修改操作。简单的想到用线段树来维护信息。

显然线段树只需要维护y/x即可,对于每一个楼房,能看见的条件就是前面楼房的y/x的严格小于当前楼房的y/x。

线段树的区间修改不再赘述。

那么怎么维护可以看到的楼房数呢?

考虑在线段树的每一个节点上用一个变量sum来表示从这个节点的左端点向右端点看时能看到多少楼房。

假设现在有一区间:1,5,8,0,7,9。维护这个区间信息的节点编号为x

x<<1维护的区间是1,5,8,从18看可以看到三个楼房,故x<<1的sum的值为3

x<<1|1维护的区间是0,7,9,从09看也可以看到三个楼房,故x<<1|1的sum的值也为3

难道x的sum值也为3+3=6?错!

这显然是不能加在一起的,x的sum的值为4。

为什么会错呢?应为右儿子x<<1|1的观察视角不是从1开始的,是从0开始的。

显然0被挡住了。

显然,为什么这道题是紫题,主要难在的怎么上传信息。(不然就是黄牌了)

首先考虑每个线段树节点在维护一个mxmx代表这个节点所代表的区间中所有的楼房中最高的高度。

上传时,由于两个儿子的sum值是已经处理好的,而左儿子的视角是跟x的视角一样的(对于上面的例子来说都是1),可以直接上传,即sum(x)+=sum(x<<1)

对于右儿子,考虑递归处理右儿子的区间,递归时带一个Mx变量表示x的左儿子的最高的楼房(右儿子再左儿子后面,原因下面解释),递归的返回值是当前处理区间可以被看到的楼房数(从x的视角看)

对于现在处理的每一个区间:

  • 如果这个区间的最高的楼房的高度都<=Mx(全部被挡住了),立即return 0
  • 如果这个区间最左边的楼房高度>Mx(可以看到),那么return 当前区间维护的sum值。
  • 如果这个区间只代表一个楼房,直接判断其能否被看到即可。
  • 对于剩下的情况,递归儿子,分两种情况讨论:

    • 如果左儿子的最高的楼房小于Mx(不能对答案有任何贡献),直接递归右儿子。
    • 否则,递归左儿子,右儿子能看到的楼房个数为当前区间sum-左儿子sum即可,(应为下面已经更新好了,只需要直接调用就好了。)

Code(文中的sum用l代替):

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. #define inf 0x3f3f3f3f
  4. #define lson x<<1
  5. #define rson x<<1|1
  6. using namespace std;
  7. const int N=1e5+2;
  8. struct Node {
  9. double mx;
  10. int l;
  11. #define m(x) tree[x].mx
  12. #define l(x) tree[x].l
  13. } tree[N<<2];
  14. int n,m;
  15. double val[N];
  16. inline void pushup_max(int x) {
  17. m(x)=max(m(x<<1),m(x<<1|1));
  18. }
  19. inline int pushup_sum(double Mx,int x,int l,int r) {
  20. if(m(x)<Mx)return 0;
  21. if(val[l]>Mx)return l(x);
  22. if(l==r)return val[l]>Mx;
  23. int mid=(l+r)>>1;
  24. if(m(lson)<=Mx)return pushup_sum(Mx,rson,mid+1,r);
  25. else return pushup_sum(Mx,lson,l,mid)+l(x)-l(lson);
  26. }
  27. inline void change(int x,int l,int r,int pos,int value) {
  28. if(l==r&&l==pos) {
  29. m(x)=(double)value/pos;
  30. l(x)=1;
  31. return;
  32. }
  33. int mid=(l+r)>>1;
  34. if(pos<=mid)change(lson,l,mid,pos,value);
  35. else if(pos>mid)change(rson,mid+1,r,pos,value);
  36. pushup_max(x);
  37. l(x)=l(lson)+pushup_sum(m(lson),rson,mid+1,r);
  38. }
  39. int main() {
  40. scanf("%d%d",&n,&m);
  41. for(register int x,y,i=1; i<=m; ++i) {
  42. scanf("%d%d",&x,&y);
  43. val[x]=(double)y/x;
  44. change(1,1,n,x,y);
  45. printf("%d\n",l(1));
  46. }
  47. return 0;
  48. }

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

  1. Solution -「洛谷 P4198」楼房重建

    \(\mathcal{Description}\)   Link.   给定点集 \(\{P_n\}\),\(P_i=(i,h_i)\),\(m\) 次修改,每次修改某个 \(h_i\),在每次修改后 ...

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

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

  3. 洛谷 P5021 [NOIP2018]赛道重建

    洛谷 P5021 [NOIP2018]赛道重建 传送门 思路 思路就是常规的思路,所以就不说了--我就是来记录一下我的\(AC\)之路的,真的是太爽了 没错--我也是一个个打的部分分,最后终于AC的, ...

  4. 题解 洛谷P5018【对称二叉树】(noip2018T4)

    \(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...

  5. 题解 洛谷 P3396 【哈希冲突】(根号分治)

    根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...

  6. 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)

    题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...

  7. 题解-洛谷P4229 某位歌姬的故事

    题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...

  8. 题解-洛谷P4724 【模板】三维凸包

    洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...

  9. 题解-洛谷P4859 已经没有什么好害怕的了

    洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...

随机推荐

  1. context:property-placeholder作用

    原文地址:http://blog.sina.com.cn/s/blog_a0de59cf0101dqeb.html spring去加载,这个元素的写法如下: <context:property- ...

  2. Gym 100962J Jimi Hendrix (树形DP)

    题意:给定一棵树,然后每条边有一个字母,然后给定一行字符串,问你能不能从这棵树上找到,并输出两个端点. 析:树形DP,先进行递归到叶子结点,然后再回溯,在回溯的时候要四个值,一个是正着匹配的长度和端点 ...

  3. SSM整合(一)

    http://www.cnblogs.com/xuerong/p/6796600.html 技术点 1.基础框架-ssm (SpringMVC +Spring +MyBatis) 2.数据库MySqQ ...

  4. bzoj 4540: [Hnoi2016]序列【单调栈+线段树】

    强烈安利:http://blog.csdn.net/qq_34637390/article/details/51313126 这篇讲标记讲的非常好,这个标记非常神奇-- 首先last表示扫描到last ...

  5. 解决window.opener.obj instanceof Object会输出false的问题

    在a.html页面中: window.obj = {name: "jinbang"} 在a.html页面中打开新窗口b.html页面: console.log(window.ope ...

  6. 用jdbc连接数据库并简单执行SQL语句

    一:版本一.这种存在一个问题就是每执行一次操作都会创建一次Connection链接和且释放一次链接 1:创建pojo对象(OR映射,一个pojo类对应一张数据库表)   package com.yin ...

  7. #undef及其用法

    简    介 在后面取消以前定义的宏定义 在此程序中,我们将取消在先前程序中对预处理器的定义. #include <stdio.h> int main( void ) { #define ...

  8. Hdu 5384 Danganronpa (AC自动机模板)

    题目链接: Hdu 5384 Danganronpa 题目描述: 给出n个目标串Ai,m个模式串Bj,问每个目标串中m个模式串出现的次数总和为多少? 解题思路: 与Hdu 2222  Keywords ...

  9. bzoj2002 [Hnoi2010]Bounce 弹飞绵羊【分块】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 这一题除了LCT解法,还有一种更巧妙,代码量更少的解法,就是分块.先想,如果仅仅记录每 ...

  10. synchronized(1)用法简介:修饰方法,修饰语句块

    注意: 同一个对象或方法在不同线程中才出现同步问题,不同对象在不同线程互相不干扰. synchronized方法有2种用法:修饰方法,修饰语句块 1.synchronized方法 是某个对象实例内,s ...