陶陶摘苹果(线段树+单调栈)

OvO

  • 传说中的线段树+单调栈模板题
    附加一道:楼房重建
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+1;
int n,m;
int h[maxn];
struct E{int len,Max,l;}tr[maxn<<2];
int Update(int M,int i,int l,int r){
    if(tr[i].Max<=M)return 0;
    if(tr[i].l>M){return tr[i].len;}
    if(l==r)return tr[i].l>M;
    int mid=(l+r)>>1;
    if(tr[i<<1].Max<=M)return Update(M,i<<1|1,mid+1,r);
    else  return tr[i].len-tr[i<<1].len+Update(M,i<<1,l,mid);
}
void Build(int i,int l,int r){
    if(l==r){tr[i].Max=h[l];tr[i].len=1;tr[i].l=h[l];return;}
    int mid=(l+r)>>1;
    Build(i<<1,l,mid);Build(i<<1|1,mid+1,r);
    tr[i].Max=max(tr[i<<1].Max,tr[i<<1|1].Max);
    tr[i].l=tr[i<<1].l;
    tr[i].len=tr[i<<1].len+Update(tr[i<<1].Max,i<<1|1,mid+1,r);
}void Change(int i,int l,int r,int pos,int k){
    if(l==r){
        tr[i].Max=k;
        tr[i].len=1;
        tr[i].l=k;
        return;
    }int mid=(l+r)>>1;
    if(mid>=pos)Change(i<<1,l,mid,pos,k);
    else Change(i<<1|1,mid+1,r,pos,k);
    tr[i].Max=max(tr[i<<1].Max,tr[i<<1|1].Max);
    tr[i].l=tr[i<<1].l;
    tr[i].len=tr[i<<1].len+Update(tr[i<<1].Max,i<<1|1,mid+1,r); 
}

int main(){
freopen("taopapp.in","r",stdin);
    freopen("taopapp.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&h[i]);
    }Build(1,1,n); 
    for(int i=1;i<=m;i++){
        int pos,H;scanf("%d%d",&pos,&H);  
        Change(1,1,n,pos,H); 
        printf("%d
",tr[1].len); 
        Change(1,1,n,pos,h[pos]);  
    }
    return 0;
}