楼房重建 HYSBZ - 2957>>>>>分块or线段树

楼房重建 HYSBZ - 2957;

分块大法好啊>>分块大法妙啊>>太6了>>太暴力了
分块的思路:维护每一块的上升子序列>>该子序列中以斜率为值进行维护>>
每次更新楼房高度,需要暴力更新该块的上升子序列
每次查询答案:以上一块的最大斜率为起点值>>二分查找>>拼接起来
复杂度是sqrt(n)*log(sqrt(n))
所以总复杂度是>>m*sqrt(n)log(sqrt(n));

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,m,x,y,blo,cnt;
int bel[N],l[500],r[500],num[500],ans;
double b[N];
double s[500][500];
void build(){
    cnt=n/blo;if(n%blo) cnt++;
    for(int i=1;i<=n;i++) bel[i]=(i-1)/blo+1;
    for(int i=1;i<=cnt;i++) l[i]=(i-1)*blo+1,r[i]=min(i*blo,n);
}
void update(int x,int y){
    b[x]=1.0*y/x;
    x=bel[x];num[x]=0;double last=0;
    for(int i=l[x];i<=r[x];i++) if(b[i]>last){
        num[x]++;s[x][num[x]]=b[i];last=b[i];
    }
    last=s[1][num[1]];ans=num[1];
    for(int i=2;i<=cnt;i++){
        int pos=upper_bound(s[i]+1,s[i]+num[i]+1,last)-s[i];
        if(pos>num[i]||pos<1) continue;
        last=max(last,s[i][num[i]]);
        ans+=(num[i]-pos+1);
    }
}
int main(){
    scanf("%d%d",&n,&m);blo=sqrt(n);
    build();
    for(int i=1;i<=n;i++) bel[i]=(i-1)/blo+1;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        update(x,y);
        printf("%d\n",ans);
    }
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/vainglory/p/9177491.html