【BZOJ2957】—楼房重建(线段树维护单调序列)

传送门

发现如果左边比右边最高的高的话左边肯定右边的就没用了
然后就是一个单调栈
用线段树维护一下就可以了
具体可以看代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int read(){
    char ch=getchar();
    int res=0,f=1;
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
    return res*f;
}
const int N=100005;
int ans[N<<2],n,m;
double tr[N<<2];
#define lc (u<<1)
#define rc ((u<<1)|1)
#define mid ((l+r)>>1)
inline int query(int u,int l,int r,double k){
    if(l==r)return tr[u]>k;
    if(tr[lc]<=k)return query(rc,mid+1,r,k);
    else return ans[u]-ans[lc]+query(lc,l,mid,k);
}
inline void pushup(int u,int l,int r){
    tr[u]=max(tr[lc],tr[rc]);
    ans[u]=ans[lc]+query(rc,mid+1,r,tr[lc]);
}
inline void update(int u,int l,int r,int p,double k){
    if(l==r){tr[u]=k,ans[u]=1;return;}
    if(p<=mid)update(lc,l,mid,p,k);
    else update(rc,mid+1,r,p,k);
    pushup(u,l,r);
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=m;i++){
        double x=read(),y=read();
        update(1,1,n,x,y/x);cout<<ans[1]<<'\n';
    }
}
posted @ 2019-03-02 16:55  Stargazer_cykoi  阅读(160)  评论(0编辑  收藏  举报