zoukankan      html  css  js  c++  java
  • bzoj 2957 楼房重建

    bzoj 2957 楼房重建

    Description

    小A的楼房外有一大片施工工地,工地上有N栋待建的楼房。每天,这片工地上的房子拆了又建、建了又拆。他经常无聊地看着窗外发呆,数自己能够看到多少栋房子。

    为了简化问题,我们考虑这些事件发生在一个二维平面上。小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段表示,其中Hi为第i栋楼房的高度。如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的。

    施工队的建造总共进行了M天。初始时,所有楼房都还没有开始建造,它们的高度均为0。在第i天,建筑队将会将横坐标为Xi的房屋的高度变为Yi(高度可以比原来大---修建,也可以比原来小---拆除,甚至可以保持不变---建筑队这天什么事也没做)。请你帮小A数数每天在建筑队完工之后,他能看到多少栋楼房?

    Input

    第一行两个正整数N,M

    接下来M行,每行两个正整数Xi,Yi

    Output

    M行,第i行一个整数表示第i天过后小A能看到的楼房有多少栋

    这道题实际上就是让我们维护最长上升子序列,我们可以维护一棵线段树,每个节点保存两个信息,一个是区间最大斜率maxl,还有一个就是区间LIS长度tr.难点在于如何将两个区间合并.我们考虑以下三种情况:

    我们先记父节点左区间的maxl为v,考虑右子区间.(因为答案至少为左子区间的答案)我们再记右子区间的左右儿子的maxl分别为maxl1,maxl2.

    • 1.右子区间整体的maxl<v,则贡献为0,返回.
    • 2.maxl1<=v,则右子区间的左儿子贡献为0,去算右子区间的右儿子.
    • 3.maxl1>v,我们注意到一个数斜率的改变只会影响到它后面的数,而如果maxl1>v的话,则v后面会被右儿子的一个左子区间的一个数给"挡住",那么它的改变是不会影响到maxl1后面的数的,所以右子区间不受影响,所以答案是右子区间的所有答案(注意:是tr[id]-tr[id<<1],因为右子区间的答案是通过左子区间算的),加上递归查询后的左子区间答案.

    代码如下

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    static const int maxm=1e6+10;
    
    int tr[maxm],lft[maxm],rht[maxm];
    double maxl[maxm];
    int n,m;
    
    void build(int id,int l,int r){
    	lft[id]=l;rht[id]=r;
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	build(id<<1,l,mid);
    	build(id<<1|1,mid+1,r);
    }
    
    int calc(int id,int l,int r,double v){
    	int mid=(l+r)>>1;
    	if(l==r)return maxl[id]>v;
    	if(maxl[id]<=v)return 0;
    	if(maxl[id<<1]<=v)return calc(id<<1|1,mid+1,r,v);
    	else return calc(id<<1,l,mid,v)+tr[id]-tr[id<<1];
    }
    
    void modify(int id,int pos,double v){
    	if(lft[id]==rht[id]){
    		tr[id]=1;
    		maxl[id]=v;
    		return;
    	}
    	int l=lft[id];int r=rht[id];int mid=(l+r)>>1;
    	if(pos<=mid)modify(id<<1,pos,v);
    	else modify(id<<1|1,pos,v);
    	tr[id]=tr[id<<1]+calc(id<<1|1,mid+1,r,maxl[id<<1]);
    	maxl[id]=max(maxl[id<<1],maxl[id<<1|1]);
    }
    
    int main(){
    	int x,y;
    	scanf("%d%d",&n,&m);
    	build(1,1,n);
    	
    	while(m--){
    		scanf("%d%d",&x,&y);
    		double l=(double)y/(double)x;
    		modify(1,x,l);
    		printf("%d
    ",tr[1]);
    	}
    
    	return 0;
    }
    

    点我进入AC通道

  • 相关阅读:
    关于Maya Viewport 2.0 API 开发的介绍视频
    春节大假
    Some tips about the life cycle of Maya thread pool
    Can I compile and run Dx11Shader for Maya 2015 on my side?
    How to get current deformed vertex positions in MoBu?
    想加入全球首届的 欧特克云加速计划吗?
    三本毕业(非科班),四次阿里巴巴面试,终拿 offer(大厂面经)
    mac、window版编辑器 webstorm 2016... 永久破解方法。
    node 搭载本地代理,处理web本地开发跨域问题
    js 一维数组,转成嵌套数组
  • 原文地址:https://www.cnblogs.com/Exbilar/p/6696584.html
Copyright © 2011-2022 走看看