zoukankan      html  css  js  c++  java
  • 【分块】bzoj2957 楼房重建

    http://www.cnblogs.com/wmrv587/p/3843681.html

    ORZ 分块大爷。思路很神奇也很清晰。

    把 块内最值 和 块内有序 两种良好的性质结合起来,非常棒地解决了这个问题。

    图中黑色的楼房即为每个块内的“可视序列”,显而易见,在块内它们的K(斜率)是单增的。

    由于上图中第一个块的maxK比后面两个块的maxK都要大,所以后两个块对答案没有贡献,这也是显然的。这就是维护maxK的意义所在。

    否则,若一个块可以更新maxK的话,则其中的部分楼房是“可见的”,具体来说,就是在那个比之前的maxK要大的楼房的后面的在可视序列中的楼房数。<---请从方链接看原版题解。

    另外,并不会像他说的,基本不会T,如果把块大小开得合适。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<vector>
     4 #include<cmath>
     5 #include<cstring>
     6 using namespace std;
     7 inline double max(const double &a,const double &b){return a>b?a:b;}
     8 vector<double>See[320];
     9 double k[100001];
    10 int sz,sum,l[320],r[320],num[100001],n,m,x,y;
    11 double maxv[320];
    12 int Res,Num;char C,CH[12];
    13 inline int G()
    14 {
    15     Res=0;C='*'; 
    16     while(C<'0'||C>'9')C=getchar();
    17     while(C>='0'&&C<='9'){Res=Res*10+(C-'0');C=getchar();}
    18     return Res;
    19 }
    20 inline void P(int x)
    21 {
    22     Num=0;if(!x){putchar('0');puts("");return;}
    23     while(x>0)CH[++Num]=x%10,x/=10;
    24     while(Num)putchar(CH[Num--]+48);
    25     puts("");
    26 }
    27 void makeblock()
    28 {
    29     memset(maxv,0,sizeof(maxv));
    30     sz=sqrt((double)n*1.05);
    31     for(sum=1;sum*sz<n;sum++)
    32       {
    33         l[sum]=(sum-1)*sz+1;
    34         r[sum]=sum*sz;
    35         for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
    36       }
    37     l[sum]=sz*(sum-1)+1;
    38     r[sum]=n;
    39     for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
    40 }
    41 inline void update()
    42 {
    43     k[x]=(double)y/x;
    44     See[num[x]].clear();
    45     maxv[num[x]]=0.0;
    46     for(int i=l[num[x]];i<=r[num[x]];i++)
    47       if(k[i]>maxv[num[x]])
    48         {
    49           maxv[num[x]]=k[i];
    50           See[num[x]].push_back(k[i]);
    51         }
    52 }
    53 inline void query()
    54 {
    55     int ans=0;double tmp=0.0;
    56     for(int i=1;i<=sum;i++)
    57       if(!See[i].empty())
    58         {
    59             ans+=See[i].end()-upper_bound(See[i].begin(),See[i].end(),tmp);
    60             tmp=max(tmp,maxv[i]);
    61         }
    62     P(ans);
    63 }
    64 int main()
    65 {
    66     n=G();m=G();makeblock();
    67     for(int i=1;i<=m;i++){x=G();y=G();update();query();}
    68     return 0;
    69 }
  • 相关阅读:
    Oracle 操作数据库(增删改语句)
    web----框架基础
    js----DOM对象
    易错之for循环
    python调用修改变量新方法
    js----基础
    web----Twisted
    web----Socket
    python----面向对象(2)
    python----面向对象
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4024671.html
Copyright © 2011-2022 走看看