bzoj 2957 楼房重建 (线段树+思路)

链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2957

思路:

用分块可以很简单的过掉,但是这道题也可以用线段树写。

分类讨论左区间最大值对右区间取值的影响,这样每次都只计算左右区间其中一个,复杂度就降成了logn.

 

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1

const int M = 1e5 + 10;
double mx[M<<2];
int sum[M<<2];
int query(double c,int l,int r,int rt){
    mid;
    if(l == r) return mx[rt] > c;
    if(mx[rt] <= c) return 0;
    if(mx[rt<<1] <= c) return query(c,rson);
    else return sum[rt] - sum[rt<<1] + query(c,lson);
}

void update(int p,double c,int l,int r,int rt){
    if(l == r){
        sum[rt] = 1;
        mx[rt] = c;
        return ;
    }
    mid;
    if(p <= m) update(p,c,lson);
    else update(p,c,rson);
    mx[rt] = max(mx[rt<<1],mx[rt<<1|1]);
    sum[rt] = sum[rt<<1] + query(mx[rt<<1],rson);
}

int main()
{
    int n,m,x,y;
    scanf("%d%d",&n,&m);
    while(m--){
        scanf("%d%d",&x,&y);
        double c = (double)y/x;
        update(x,c,1,n,1);
        printf("%d\n",sum[1]);
    }
}

 

posted @ 2018-10-16 21:31  冥想选手  阅读(136)  评论(0编辑  收藏  举报