zoukankan      html  css  js  c++  java
  • 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能看到的楼房有多少栋

    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

    HINT

    Source

    中国国家队清华集训 2012-2013 第一天

    这是G10的联赛模拟题。。。无聊想用分块来写一写。。。

    一个点能被看到,当且仅当前面不存在斜率大于等于他的点。

    考虑分块,对每一个块,维护一个斜率上升序列和斜率最大值。

    查询的话我们可以从前往后做,维护一个前缀的最大斜率。。

    然后对于整块二分查找第一个斜率大于当前最大斜率的位置(upper_bound),然后把后面的计入答案,散点暴力即可。

    修改的话就重构斜率上升序列和维护最大值;

    查询的复杂度为n*sqrt(n)*logn,修改的复杂度为n*sqrt(n);

    第一次交竟然开的是int。。。bzoj 一版绿就这样没了。。。

    // MADE BY QT666
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #define RG register
    using namespace std;
    typedef long long ll;
    const int N=100050;
    const double eps=1e-6;
    int pos[N],block,cnt,L[N],R[N],n,m,num[400];
    double g[N],Max[400],bl[400][400];
    void update(int x,double val){
      g[x]=val;int l=L[pos[x]],r=R[pos[x]];
      num[pos[x]]=0;Max[pos[x]]=0;
      for(RG int i=l;i<=r;i++){
        if(g[i]-0>=eps&&g[i]>Max[pos[x]]){
          bl[pos[x]][++num[pos[x]]]=g[i];
          Max[pos[x]]=max(Max[pos[x]],g[i]);
        }
      }
    }
    int query(int l,int r){
      double ret=0;int res=0;
      if(pos[l]==pos[r]){
        for(RG int i=l;i<=r;i++){
          if(g[i]-0>=eps&&g[i]>ret) ret=max(ret,g[i]),res++;
        }
      }
      else{
        for(RG int i=l;i<=R[pos[l]];i++){
          if(g[i]-0>=eps&&g[i]>ret) ret=max(ret,g[i]),res++;
        }
        for(RG int i=pos[l]+1;i<=pos[r]-1;i++){
          if(bl[i][num[i]]>ret){
        int gg=upper_bound(bl[i]+1,bl[i]+num[i]+1,ret)-bl[i];
        if(bl[i][gg]>ret) res+=(num[i]-gg+1);
        ret=max(ret,Max[i]);
          }
        }
        for(RG int i=L[pos[r]];i<=r;i++){
          if(g[i]-0>=eps&&g[i]>ret) ret=max(ret,g[i]),res++;
        }
      }
      return res;
    }
    int main(){
      scanf("%d%d",&n,&m);
      block=sqrt(n);cnt=n/block;
      if(n%block) cnt++;
      for(RG int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
      for(RG int i=1;i<=cnt;i++) L[i]=(i-1)*block+1,R[i]=i*block;
      R[cnt]=n;
      for(RG int i=1;i<=m;i++){
        int x,h;scanf("%d%d",&x,&h);
        update(x,h*1.0/x);
        printf("%d
    ",query(1,n));
      }
      return 0;
    }
    

      

  • 相关阅读:
    2021,6,10 xjzx 模拟考试
    平衡树(二)——Treap
    AtCoder Beginner Contest 204 A-E简要题解
    POJ 2311 Cutting Game 题解
    Codeforces 990G GCD Counting 题解
    NOI2021 SDPTT D2T1 我已经完全理解了 DFS 序线段树 题解
    第三届山东省青少年创意编程与智能设计大赛总结
    Luogu P6042 「ACOI2020」学园祭 题解
    联合省选2021 游记
    Codeforces 1498E Two Houses 题解 —— 如何用结论吊打标算
  • 原文地址:https://www.cnblogs.com/qt666/p/7219500.html
Copyright © 2011-2022 走看看