[BZOJ2957] 楼房重建 分块

来源:互联网 发布:window10引导ubuntu 编辑:程序博客网 时间:2024/06/08 04:23

BZOJ2957: 楼房重建

貌似是一道线段树的题,然而线段树太烧脑想不出来,只能暴力的玩分块。
分块很好想的,维护 √n 个块,每块都按照斜率单调递增的标准来维护。
查询把所有块for一遍。
因为每个块的斜率都是单调递增的,对于每个块使用二分可以节省一点点时间,就可以偷税(愉悦)的Accepted了~


抱怨几句

玩个斜率就不该用float= =
就为了在BZOJ的status上让me的结果好看一点,用起了float省空间,然后开始了漫漫的WA之旅= =


这里是代码~~~(附赠调试信息)
BZOJ 4112ms 2416Kb
其实可以先预处理出每个楼房在哪个块,每个块的开始点和结束点的位置,再小小的加一个读优,可能还会快一点。

#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>using namespace std;int n,m,topp[320],bsiz,btot;double maxslo[320],nslo[100001],nblo[320][320];void modify(int pos){    int bp=pos/bsiz,epos=min((bp+1)*bsiz,n);    //printf("modify : bp=%d epos=%d\n",bp,epos);    double maxs=0.0;    topp[bp]=0;    for(int i=bp*bsiz+1;i<=epos;i++){        //printf("i=%d\n",i);        if(nslo[i]>maxs){            //printf("slove i = %f   maxs=%f  ",nslo[i],maxs);            nblo[bp][++topp[bp]]=nslo[i];            maxs=nslo[i];            //printf("  %f\n",maxs);        }    }    maxslo[bp]=maxs;}void query(){    int seen=topp[0];    double last=maxslo[0];//  printf("query: seen=topp[0]=%d  last=block slove[0]=%f\n",seen,maxslo[0]);    for(int i=1;i<=btot;i++){        int L=1,R=topp[i],mid;        while(L<=R){            mid=(L+R)>>1;            if(nblo[i][mid]>last)   R=mid-1;            else L=mid+1;        }        seen+=topp[i]-L+1;last=max(maxslo[i],last);        //printf("i=%d seen[%d]=%d L=%d\n",i,i,seen,L);    }    printf("%d\n",seen);}int main(){    int pos,h;    scanf("%d%d",&n,&m);    bsiz=sqrt(n);//printf("block size=%d\n\n",bsiz);    if(n%bsiz)        btot=(int)(n/bsiz);    else btot=(int)(n/bsiz)-1;    //printf("btot=%d\n",btot);    for(int i=1;i<=m;i++){        scanf("%d%d",&pos,&h);        nslo[pos]=(double)h/pos;        //printf("slove %d =%f\n",pos,nslo[pos]);        modify(pos-1);        query();    }}