楼房重建

题解

很容易发现,一个楼房能够被看到当且仅当它前面的楼房的斜率都比它的小。
我们显然可以把斜率这东西离散化下来,当成一个权值,所以我们相当于要事实维护有多少个不同的前缀最大值。
首先这应该很容易 come up with 一种 O ( m log ⁡ 2 n ) O\left(m\log^2n\right) O(mlog2n)的树套树做法,但由于它太麻烦了,这里不会讲它,我们来讲一种更简单的线段树做法。
我们不妨在线段树的每个节点上维护一个 v a l i val_{i} vali​表示该区间的不同的前缀最大值个数。
显然, v a l r t val_{rt} valrt​就是答案,关键是我们怎么在合并的过程中维护我们的 v a l r t val_{rt} valrt​。
显然,左边的 v a l l s o n val_{lson} vallson​,而右边则应该是比 m a x x l s o n maxx_{lson} maxxlson​(即左儿子)大的不同的前缀最大值数量。
我们可以定义一个函数 s a k u r a ( r t , k ) sakura(rt,k) sakura(rt,k)表示在 r t rt rt的区间内比 k k k大的前缀最大值数量。

  • 如果 m a x x l s o n > k maxx_{lson}>k maxxlson​>k,显然我们的前缀最大值显然在左儿子的区间内就已然超过了 k k k,我们只需要处理左儿子有多少个大于 k k k的前缀最大值,返回 m a x x r t − m a x x l s o n + s a k u r a ( l s o n , k ) maxx_{rt}-maxx_{lson}+sakura(lson,k) maxxrt​−maxxlson​+sakura(lson,k)。
  • 如果 m a x x l s o n ⩽ k ∧ m a x x r s o n > k maxx_{lson}\leqslant k\wedge maxx_{rson}>k maxxlson​⩽k∧maxxrson​>k,显然我们的前缀最大值是在右儿子的区间内超过 k k k的,由于左边最大值小于 k k k,显然不会对右边那些大于 k k k的前缀最大值造成影响,直接在右边求就是了,返回 s a k u r a ( r s o n , k ) sakura(rson,k) sakura(rson,k)。
  • 如果 m a x x l s o n ⩽ k ∧ m a x x r s o n ⩽ k maxx_{lson}\leqslant k\wedge maxx_{rson}\leqslant k maxxlson​⩽k∧maxxrson​⩽k,那就不可能出现大于 k k k的前缀最大值了,直接返回 0 0 0。

于是,这样我们就可以 O ( log ⁡ n ) O\left(\log\,n\right) O(logn)地更新单点 v a l val val了。
由于我们每次修改会更新 log ⁡ n \log\,n logn个点的 v a l val val,总共会修改 O ( m ) O\left(m\right) O(m)次,总时间复杂度 O ( n log ⁡ 2 n ) O\left(n\log^2n\right) O(nlog2n),但代码明显好打了。

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 200005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL;
typedef long double ld;
const int INF=0x3f3f3f3f;
const int mo=1e9+7;
const int inv2=499122177;
const double jzm=0.997;
const int zero=15;
const int n1=200;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
struct tann{int x,y;tann(){x=y=0;}tann(int X,int Y){x=X;y=Y;}bool operator == (const tann &rhs)const{return x==rhs.x&&y==rhs.y;}bool operator < (const tann &rhs)const{return 1ll*x*rhs.y<1ll*rhs.x*y;} bool operator > (const tann &rhs)const{return 1ll*x*rhs.y>1ll*rhs.x*y;}
}b[MAXN];
int n,m,totb;
struct ming{int x,y,val;tann vp;}s[MAXN];
class SegmentTree{private:int maxx[MAXN<<2],val[MAXN<<2];int sakura(int rt,int l,int r,int k){if(l==r)return maxx[rt]>k;int mid=l+r>>1;if(maxx[lson]>k)return val[rt]-val[lson]+sakura(lson,l,mid,k);if(maxx[rson]>k)return sakura(rson,mid+1,r,k);return 0;}public:void modify(int rt,int l,int r,int ai,int aw){if(l>r||l>ai||r<ai)return ;int mid=l+r>>1;if(l==r){maxx[rt]=aw;val[rt]=1;return ;}if(ai<=mid)modify(lson,l,mid,ai,aw);if(ai>mid)modify(rson,mid+1,r,ai,aw);maxx[rt]=max(maxx[lson],maxx[rson]);val[rt]=val[lson]+sakura(rson,mid+1,r,maxx[lson]);}int query(int rt){return val[rt];}
}T;
signed main(){read(n);read(m);for(int i=1;i<=m;i++){read(s[i].x),read(s[i].y);int d=gcd(s[i].y,s[i].x);b[++totb]=tann(s[i].y/d,s[i].x/d);s[i].vp=b[totb];}sort(b+1,b+totb+1);totb=unique(b+1,b+totb+1)-b-1;for(int i=1;i<=m;i++){s[i].val=lower_bound(b+1,b+totb+1,s[i].vp)-b;T.modify(1,1,n,s[i].x,s[i].val);printf("%d\n",T.query(1)); }return 0;
}

[BZOJ2957]楼房重建相关推荐

  1. BZOJ2957:楼房重建(线段树)

    Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...

  2. BZOJ2957 楼房重建

    Description 平面上有\(n\)个位置\(1\dots n\),第\(i\)个位置有一个高为\(H_i\)的楼房:所有\(H\)初始值为\(0\).每次修改一个\(H_i\),求修改后从\( ...

  3. BZOJ2957楼房重建

    传送门  https://www.luogu.org/problemnew/show/P4198 蒟蒻渣渣禹看到这个题时十分不想写线段树emmmm 于是乎....分块!!! 分块.思路就是:如果一个楼 ...

  4. Bzoj2957: 楼房重建

    题目 传送门 Sol 线段树,维护斜率单增的最高点和长度 更新,以下的都是指斜率 当前点的左儿子更新上来,右儿子递归 如果右儿子的左儿子的最大值大于左儿子的 加上算出右儿子的右儿子的贡献(右儿子贡献减 ...

  5. bzoj-2957 楼房重建

    题意: 数轴上有n个楼,分别在1~n这些点上: m次查询.每次改变一个楼的高度,问从(0,0)这个点能够看到多少楼: 题解: 对于一个楼来说要想看到这个楼.那么前面的楼的斜率一定比这个楼小: 那么考虑 ...

  6. BZOJ 2957楼房重建

    传送门 线段树 //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include< ...

  7. P4198 楼房重建 线段树 + 区间合并

    传送门 文章目录 题意: 思路: 题意: 题面有点问题,按照人类正常的理解来就好啦. 思路: 可以想到维护每个位置的一个斜率,模拟的话就是从第一个位置开始向后选,当某个位置斜率大于当前位置的时候,答案 ...

  8. LG P4198 楼房重建(线段树)

    LG P4198 楼房重建 Solution 基础的线段树题,虽然我还不熟练就是了. 大概就是单点修改,求全局的极大子序列. 我们需要维护一个区间最大值aaa和极大子序列长度sss. 合并xxx的左右 ...

  9. [luogu P4198] 楼房重建(线段树 + 思维)

    luogu 楼房重建 problem solution code problem 洛谷链接 solution 非常巧妙的一道题,对线段树的运用很灵活. 显然这个与原点的连线可以想到将每个点转化为与原点 ...

最新文章

  1. USEARCH11发布,新功能简介
  2. suse卸载自带java_在openSUSE 13.1下安装卸载openjdk以及Oracle JDK
  3. 解决ASP.NET上传文件大小限制
  4. UVA11324-- The Largest Clique(SCC+DP)
  5. hadoop配置文件的加载机制
  6. 图论——Tarjan 初步 DFS序+时间戳+欧拉序
  7. 吴恩达机器学习+林轩田机器学习+高等数学和线性代数等视频领取
  8. 科大奥锐实验报告霍尔效应_大学物理实验报告系列之霍尔效应
  9. Java多线程学习九:如何正确关闭线程池?shutdown 和 shutdownNow 的区别
  10. parseInt() 函数 转载
  11. 【tf.keras.Model】构建模型小结(部分问题未解决)
  12. [2018.07.31 T3] 第三题
  13. js基础-10-url,src,href的理解
  14. gmail不支持html格式,gmail邮箱附件如何以html格式查看
  15. 跟华为云一起,做未来城市的解谜人
  16. JS 的内联模式与外联模式
  17. 清华贫困生的树洞,没有卖惨与诉苦,那股韧劲直抵人心
  18. 用SAPI做一个聊天模拟器
  19. WRF——OBSGRID使用方法(gfortran编译)
  20. markdown写公式的角标与下标

热门文章

  1. Y2_J2EE_自定义JSP标签
  2. 基于树莓派摄像头的冷水珊瑚礁科考
  3. 客户需求太多,如何有效沟通完成项目?
  4. 常见的端口扫描类型及端口扫描原理
  5. React:我们即将和后端 API 告别?
  6. Java中的栈内存和堆内存
  7. vue中使用axios请求数据过程
  8. SubSonic3.0插件分页查询速度测试
  9. sqlite 超小白笔记
  10. The requested list key '#request.localprovi' could not be resolved as a collection/array/map/enumera