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

    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

    正解:线段树。

    其实去年的联赛模拟就考过这题了,比较无聊所以重做一遍。。

    这是一个线段树的板子题,首先我们考虑维护一个区间的可见点数$sum$,那么答案就是$sum[rt]$。

    如何在单点修改以后维护$sum$?我们考虑一个区间的$sum$,首先左儿子的$sum$肯定是直接加上的。

    同时记$max1$为左儿子的斜率最大值,我们可以递归右儿子来找右儿子对这个区间的贡献。

    $max2$为右儿子的左儿子的斜率最大值,如果$max2<max1$,那么我们可以不用管右儿子的左儿子了,直接递归右儿子的右儿子即可。

    如果$max2>max1$,我们可以发现,右儿子的右儿子的贡献就是右儿子的右儿子在右儿子这个区间的贡献,也就是$sum[rs]-sum[ls[rs]]$,那么直接递归右儿子的左儿子计算即可。

    到叶子结点的时候直接判断斜率大小关系就行了。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 #define N (200010)
     6 #define ls (x<<1)
     7 #define rs (x<<1|1)
     8 #define eps (1e-10)
     9 
    10 using namespace std;
    11 
    12 int sum[N<<2],n,m;
    13 double mx[N<<2],k;
    14  
    15 il int gi(){
    16   RG int x=0,q=1; RG char ch=getchar();
    17   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    18   if (ch=='-') q=-1,ch=getchar();
    19   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    20   return q*x;
    21 }
    22 
    23 il int calc(RG int x,RG int l,RG int r,RG double k){
    24   if (l==r) return mx[x]>k; RG int mid=(l+r)>>1;
    25   if (k<mx[ls]) return calc(ls,l,mid,k)+sum[x]-sum[ls];
    26   else return calc(rs,mid+1,r,k);
    27 }
    28 
    29 il void update(RG int x,RG int l,RG int r,RG int p,RG double k){
    30   if (l==r){ mx[x]=k,sum[x]=fabs(k)>=eps; return; } RG int mid=(l+r)>>1;
    31   p<=mid ? update(ls,l,mid,p,k) : update(rs,mid+1,r,p,k);
    32   sum[x]=sum[ls]+calc(rs,mid+1,r,mx[ls]),mx[x]=max(mx[ls],mx[rs]); return;
    33 }
    34 
    35 int main(){
    36 #ifndef ONLINE_JUDGE
    37   freopen("rebuild.in","r",stdin);
    38   freopen("rebuild.out","w",stdout);
    39 #endif
    40   n=gi(),m=gi();
    41   for (RG int i=1,x,y;i<=m;++i){
    42     x=gi(),y=gi(),k=1.0*y/x;
    43     update(1,1,n,x,k),printf("%d
    ",sum[1]);
    44   }
    45   return 0;
    46 }
  • 相关阅读:
    xml学习_上篇
    回首博客 年满一周年,记录90个点滴瞬间
    编写PHP代码总结
    代码高亮插件SyntaxHighlighter
    记忆,是一座沙城!
    dreamweaver中的 map怎么调用?_制作热点图像区域
    手机端rem如何适配_rem详解及使用方法
    彻底弄懂css中单位px和em,rem的区别
    JavaScript学习方法
    10条建议让你创建更好的jQuery插件
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7497253.html
Copyright © 2011-2022 走看看