BZOJ 2597 楼房重建 (分块/线段树)

题意

一个1e5的double数组,前面大的元素会挡住后面小的元素,有1e5个操作,每次改变一个元素的值,问你每次改完之后有多少元素没有被挡

思路

考虑分块,对每一个块维护一个单独的答案,那么总的答案一定是各块单独的答案的一部分合起来
每次修改之后只需要重新计算本块的答案,并且对每一块二分接上的位置,并统计答案

线段树做法待更

代码

分块做法
开始精度设置的1e-6,wa了

int n,t,m;
double a[maxn];
double mx[maxn];
int cnt[maxn];
int go(int x){
    return (x+t-1)/t;
}
vector<double>v[maxn];
int main() {
    scanf("%d %d", &n,&m);
    t=sqrt(n);
    int tot = (n+t-1)/t;
    v[0].pb(0);
    for(int i = 1; i <= m; i++){
        int x,y;
        scanf("%d %d", &x ,&y);
        a[x]=1.0*y/x;
        int now = go(x);
        int l = (now-1)*t+1,r=min(n,now*t);
        double lst = 0;
        v[now].clear();
        for(int j = l; j <= r; j++){
            if(a[j]>lst+eps){
                lst=a[j];v[now].pb(a[j]);
            }
        }
        int ans = 0;
        lst =0;
        for(int j = 1; j <= tot; j++){
            int x = lower_bound(v[j].begin(),v[j].end(),lst+eps)-v[j].begin()+1;
            int tmp = v[j].size()-x+1;
            if(tmp)lst=v[j].back();
            ans+=tmp;
        }
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2020-05-28 16:59  wrjlinkkkkkk  阅读(119)  评论(0编辑  收藏  举报