【线段树】[Luogu P4198]楼房修建

显然要维护斜率区间单调递增

并且第一个必选,后一个比前一个选中的斜率大的必选

考虑如何合并两个区间

我们维护一个least值,least这个值必选,且之后选的都必须严格大于least,Push_Up的时候就像在线段树上二分一样做就好了

这样每次Push_Up是$logn$的,线段树单点修改时$logn$的,所以总复杂度是$O(nlog^2n)$的,再维护一个区间最大值可以做到一些不必要但是可以卡常的剪枝...

 1 #include<bits/stdc++.h>
 2 #define writeln(x)  write(x),puts("")
 3 #define writep(x)   write(x),putchar(‘ ‘)
 4 using namespace std;
 5 inline int read(){
 6     int ans=0,f=1;char chr=getchar();
 7     while(!isdigit(chr)){if(chr==‘-‘) f=-1;chr=getchar();}
 8     while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
 9     return ans*f;
10 }void write(int x){
11     if(x<0) putchar(‘-‘),x=-x;
12     if(x>9) write(x/10);
13     putchar(x%10+‘0‘);
14 }const int M = 2e5+5;
15 int s[M<<2],n,T;
16 double mx[M<<2],a[M];
17 #define ls (i<<1)
18 #define rs (i<<1|1)
19 #define mid (l+r>>1)
20 inline int Push(int i,int l,int r,double least){
21     if(mx[i]<=least) return 0;
22     if(a[l]>least) return s[i];
23     if(l==r) return a[l]>least;
24     if(mx[ls]<=least) return Push(rs,mid+1,r,least);
25     return Push(ls,l,mid,least)+s[i]-s[ls];
26 }inline void Push_Up(int i,int l,int r){
27     mx[i]=max(mx[ls],mx[rs]);
28     s[i]=s[ls]+Push(rs,mid+1,r,mx[ls]);
29 }void Update(int i,int l,int r,int pos,double x){
30     if(l==r)return mx[i]=x,s[i]=1,void();
31     if(pos<=mid) Update(ls,l,mid,pos,x);
32     else Update(rs,mid+1,r,pos,x);
33     Push_Up(i,l,r);
34 }int main(){
35     n=read(),T=read();
36     while(T--){
37         int x=read(),y=read();
38         a[x]=y*1.0/(x*1.0);
39         Update(1,1,n,x,y*1.0/(1.0*x));
40         printf("%d\n",s[1]);
41     }return 0;
42 }

原文地址:https://www.cnblogs.com/zhenglw/p/11723857.html

时间: 2024-12-29 06:40:03

【线段树】[Luogu P4198]楼房修建的相关文章

[Luogu P4198]楼房重建(线段树)

题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个二维平面上.小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段 表示,其中Hi为第i栋楼房的高度.如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的. 施工队的建造总共进行了M天.初始时,所有楼房都还没有开始建

[luogu] P4198 楼房重建

题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个二维平面上.小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段表示,其中Hi为第i栋楼房的高度.如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的. 施工队的建造总共进行了M天.初始时,所有楼房都还没有开始建造

[线段树] Luogu P4346 IIIDX

题目背景 Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI 内工作,离他的梦想也越来越近了. 这款音乐游戏内一般都包含了许多歌曲,歌曲越多,玩家越不易玩腻.同时,为了使玩家在游戏上氪更多的金钱花更多的时间,游戏一开始一般都不会将所有曲目公开,有些曲目你需要通关某首特定歌曲才会解锁,而且越晚解锁的曲目难度越高. 题解 先从大到小排序,每次找一个最靠左的位置,使得这个位置左边足够放下当前节点的子树 若有

[线段树] Luogu P4314 COU监控

题目描述 Bob需要一个程序来监视CPU使用率.这是一个很繁琐的过程,为了让问题更加简单,Bob会慢慢列出今天会在用计算机时做什么事. Bob会干很多事,除了跑暴力程序看视频之外,还会做出去玩玩和用鼠标乱点之类的事,甚至会一脚踢掉电源……这些事有的会让做这件事的这段时间内CPU使用率增加或减少一个值:有的事还会直接让CPU使用率变为一个值. 当然Bob会询问:在之前给出的事件影响下,CPU在某段时间内,使用率最高是多少.有时候Bob还会好奇地询问,在某段时间内CPU曾经的最高使用率是多少. 为了

[树链剖分][线段树] Luogu P2146 软件包管理器

题解 很容易发现,改变了某个软件,变的只会是该软件到根的距离+路径上所有软件的子树 那么我们怎么快速求出这个东东,安装时,考虑将x到根的路径上全部变为1,然后用线段树维护区间和用改变后-改变前就是答案 卸载的话,就将x到根的路径全部变成0,也是区间和,用改变前-改变后 区间和的话就可以用线段树来维护 代码 1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #define N 100010

楼房重建(分块/线段树)

问题: 小 A 的楼房外有一大片施工工地,工地上有 N 栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个二维平面上.小 AA 在平面上 (0,0) 点的位置,第 ii 栋楼房可以用一条连接 (i,0) 和 (i,Hi?) 的线段表示,其中 Hi? 为第 i栋楼房的高度. 如果这栋楼房上存在一个高度大于 0 的点与 (0,0)的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的. 施工队的建造

【BZOJ 2957】 2957: 楼房重建 (线段树)

2957: 楼房重建 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1753  Solved: 841 Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个二维平面上.小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段表示,其中Hi为第i栋楼房的高度.

[BZOJ 2957]楼房重建(线段树)

Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个二维平面上.小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段表示,其中Hi为第i栋楼房的高度.如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的.施工队的建造总共进行了M天.初始时,所有楼房都还

楼房重建(线段树)

楼房重建 题目描述 小A的楼房外有一大片施工工地,工地上有\(N\)栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个二维平面上.小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接\((i,0)\)和\((i,H_i)\)的线段表示,其中\(H_i\)为第\(i\)栋楼房的高度.如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的. 施工队