码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ2957: 楼房重建

时间:2018-03-09 20:28:05      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:sample   维护   algorithm   一个   可见   script   int   algo   实现   

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能看到的楼房有多少栋

Sample Input


3 4
2 4
3 6
1 1000000000
1 1

Sample Output


1
1
1
2
数据约定
  对于所有的数据1<=Xi<=N,1<=Yi<=10^9
N,M<=100000
 
 
先更正一点:如果一个楼房能被看到,那么他的斜率就比他之前的所有楼房都高
线段树好题。。。这题太神了我根本不会做。。。
首先我第一反应就是线段树了,想着维护一个最大值即可。。。
但是我好像不是很会具体的实现。。
其实挺简单的只是我比较菜
对于每一个修改,我们先问左孩子,如果左孩子的最大值比这个还大的话那就不用看右孩子了,因为他们根本看不到
如果小于的话我们就可以直接继承,然后线段树维护,每次分成两个区间
 
代码如下:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct trnode{
    int l,r,lc,rc,c;
    double maxx;
}tr[210000];int trlen;
void bt(int l,int r)
{
    int now=++trlen;
    tr[now].l=l;tr[now].r=r;tr[now].c=0;
    tr[now].lc=tr[now].rc=-1;tr[now].maxx=0.0;
    if(l<r)
    {
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
    }
}
int n,m;
int get(int now,double maxx)
{
    if(now==-1)return 0;
    if(tr[now].maxx<maxx)return 0;
    if(tr[now].l==tr[now].r&&tr[now].maxx>maxx)return 1;
    int lc=tr[now].lc,rc=tr[now].rc;
    if(tr[lc].maxx<=maxx)return get(rc,maxx);
    else return get(lc,maxx)+tr[now].c-tr[lc].c;
}
void change(int now,int p,double c)
{
    if(tr[now].l==tr[now].r){tr[now].c=1,tr[now].maxx=c;return ;}
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(p<=mid)change(lc,p,c);
    else change(rc,p,c);
    tr[now].maxx=max(tr[lc].maxx,tr[rc].maxx);
    tr[now].c=tr[lc].c+get(rc,tr[lc].maxx);
}
int main()
{
    scanf("%d%d",&n,&m);
    trlen=0;bt(1,n);
    while(m--)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        double c=(double)y/(double)x;
        change(1,x,c);
        printf("%d\n",tr[1].c);
    }
    return 0;
}

by_lmy

 

BZOJ2957: 楼房重建

标签:sample   维护   algorithm   一个   可见   script   int   algo   实现   

原文地址:https://www.cnblogs.com/MT-LI/p/8535499.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!