zoukankan      html  css  js  c++  java
  • 洛谷 题解 P4198 【楼房重建】

    首先明确问题,对于每栋楼房的斜率K=H/X,问题就是问有多少个楼房的K比前面所有楼房的K都要大。

    这题树套树当然可以,但是挺麻烦的,本渣觉得最简单就是分块……

    将N个楼房分成T块,不断维护每个块内楼房的可视序列,如一个块内楼房的高度分别为(3 1 4 2 6 7)那么这个块内楼房的可视序列就是(3 4 6 7)(注意不同的块内是不干扰的,如第一个块可视序列为(3 4 6),第二块的序列可以是(5 7 8))

    对于每个修改,我们只需对每个块内的楼房暴力维护可视序列就行了,O(N/T)

    对于每个询问,我们只需一个块一个块看,不断维护到目前为止的可视序列中K的最大值kmax(不在可视序列内的楼房的K值一定不大),那么对于查询每个块的时候,可以二分可视序列找到第一个大于kmax的位置,若没有则这个块的所有楼房都不可见,如果存在,那么这个位置后的此块中的可视序列楼房都能看见,那么就更新答案和kmax,不断往后做

    注意:毕竟时间比较紧,所以常数还是尽可能写小点,二分和max函数还是自己写好些,不然会爆RP…

     1 #include<cstdio>
     2 #include<cmath>
     3 const int maxn=100005,sqrn=350;
     4 int h[maxn],v[sqrn][sqrn],c[sqrn],l[sqrn],r[sqrn],bel[maxn],n,m,block,cnt,x,y,ch;
     5 void read(int&x) {
     6     x=0,ch=getchar();
     7     while(ch>'9'||ch<'0')ch=getchar();
     8     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
     9 }
    10 bool vis(int x,int y) {
    11     return (long long)h[x]*y<(long long)h[y]*x;
    12 }
    13 int bfind(int*a,int l,int r,int mx) {
    14     if(!mx)return l;
    15     if(!vis(mx,a[r]))return 0;
    16     int m=0,ans=0;
    17     while(l<=r) {
    18         m=(l+r)>>1;
    19         if(vis(mx,a[m]))ans=m,r=m-1;
    20         else l=m+1;
    21     }
    22     return ans;
    23 }
    24 void build(int x) {
    25     c[x]=0;
    26     int lst=0;
    27     for(register int i=l[x]; i<=r[x]; ++i)if(h[i])if(!lst||vis(lst,i))lst=v[x][++c[x]]=i;
    28 }
    29 int query() {
    30     int tot=0,mx=0,pos;
    31     for(register int i=1; i<=cnt; ++i)if(c[i]) {
    32             pos=bfind(v[i],1,c[i],mx);;
    33             if(pos)tot+=c[i]-pos+1,mx=v[i][c[i]];
    34         }
    35     return tot;
    36 }
    37 int main() {
    38     read(n),read(m);
    39     block=sqrt(n);
    40     cnt=n/block;
    41     if(n%block)++cnt;
    42     for(register int i=1; i<=n; ++i)bel[i]=(i-1)/block+1;
    43     for(register int i=1; i<=cnt; ++i)l[i]=(i-1)*block+1,r[i]=i*block;
    44     r[cnt]=n;
    45     for(register int i=1; i<=m; ++i) {
    46         read(x),read(y);
    47         h[x]=y;
    48         build(bel[x]);
    49         printf("%d\n",query());
    50     }
    51     return 0;
    52 }
    垃圾鸡脖的代码
  • 相关阅读:
    SHELL编程之执行环境----邹立巍的博客
    linux内核分析系列--百度
    Linux模式设计系列( 内核与应用关联思考)
    Linux内核源代码情景分析系列
    Linux内核学习和研究及嵌入式(ARM)学习和研究的开放文档
    实验楼内核分析 +图
    《Linux内核修炼之道》 系列
    和菜鸟一起学linux内核源码之基础准备篇 系列 体系结构图
    实验楼在线算法学习
    linux-0.11内核 调试教程+GCC源代码
  • 原文地址:https://www.cnblogs.com/Xchu/p/11265867.html
Copyright © 2011-2022 走看看