P4198 楼房重建 题解
P4198 楼房重建
简化题意+思路+代码在下面啦
题目描述
小 A 的楼房外有一大片施工工地,工地上有 NNN 栋待建的楼房。每天,这片工地上的房子拆了又建、建了又拆。他经常无聊地看着窗外发呆,数自己能够看到多少栋房子。
为了简化问题,我们考虑这些事件发生在一个二维平面上。小 A 在平面上 (0,0)(0,0)(0,0) 点的位置,第 iii 栋楼房可以用一条连接 (i,0)(i,0)(i,0) 和 (i,Hi)(i,H_i)(i,Hi) 的线段表示,其中 HiH_iHi 为第 iii 栋楼房的高度。如果这栋楼房上存在一个高度大于 000 的点与 (0,0)(0,0)(0,0) 的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的。
施工队的建造总共进行了 MMM 天。初始时,所有楼房都还没有开始建造,它们的高度均为 000。在第 iii 天,建筑队将会将横坐标为 XiX_iXi 的房屋的高度变为 YiY_iYi(高度可以比原来大—修建,也可以比原来小—拆除,甚至可以保持不变—建筑队这天什么事也没做)。请你帮小 A 数数每天在建筑队完工之后,他能看到多少栋楼房?
输入格式
第一行两个正整数 N,MN,MN,M。
接下来 MMM 行,每行两个正整数 Xi,YiX_i,Y_iXi,Yi。
输出格式
MMM 行,第 iii 行一个整数表示第 iii 天过后小 A 能看到的楼房有多少栋。
输入输出样例 #1
输入 #1
3 4
2 4
3 6
1 1000000000
1 1
输出 #1
1
1
1
2
说明/提示
对于 100%100\%100% 的数据,1≤Xi≤N1 \le X_i \le N1≤Xi≤N,1≤Yi≤1091 \le Y_i \le 10^91≤Yi≤109,1≤N,M≤1051\le N,M \le 10^51≤N,M≤105。
简化题意:
站在 000 处,建造队造了 nnn 天,每天会将 xix_ixi 位置的房屋高度变为 yiy_iyi,问每次完工后,能看到多少栋楼房。(依次递增就能看到)。n,m≤105n,m\leq 10^5n,m≤105。
已完成楼房建造大学习。
线段树。
答案是:大于前一个的必选,小于等于前一选择的必不选。
线段树维护区间最大值和区间内答案长度。最大值的修改直接更新即可。
对于答案长度的合并,当我们合并左右区间时,左区间长度必不变,我们肯定会选择完整的左区间。右区间则可能被左区间的楼遮挡,所以我们递归进去(设左区间最大值为lst):
1.若长度为1,则判断此节点与lst大小即可。
2.若该节点的左半部分最大值大于lst,则右半部分肯定都能选,答案是 tr[p].sum−tr[p<<1].sumtr[p].sum-tr[p<<1].sumtr[p].sum−tr[p<<1].sum !不是右半部分的sum哦。接着再递归左半部分。
3.若左半部分小于lst,递归右半部分。
重点部分:
void pushup2(int p,double lst,int l,int r){if(tr[p].mx<=lst) return ;if(a[l]>lst) {ad+=tr[p].sum;return ;}if(l==r) {ad+=(tr[p].mx>lst);return ;}int mid=(l+r)>>1;if(tr[p<<1].mx<=lst) pushup2(p<<1|1,lst,mid+1,r);else {pushup2(p<<1,lst,l,mid);ad+=tr[p].sum-tr[p<<1].sum;}
}
code:MYJ_aiie
