Logo syxx_tangchenhui的博客

博客

不会做P905 HILO怎么办

2023-06-04 21:08:35 By syxx_tangchenhui
/*
作者也不会做
网上找了份代码 Ctrl+C 了下来
再用 Ctrl+V 大法就过了
还请谅解
另:(也是网上抄的)
    线段树太垃圾了
    大神们可以用平衡树求前驱后继来求 le 和 ri (即左区间(left)和右区间(right)) 
*/ 
#include<bits/stdc++.h>
#define N 200005
using namespace std;
int le[4*N],ri[4*N],f[4*N],cnt[4*N],h[N],n;

//线段树求解左区间 

void pushdown_l(int k){
    if (le[k]==0) return;
    le[k<<1]=max(le[k<<1],le[k]);
    le[k<<1|1]=max(le[k<<1|1],le[k]);
}
void add_l(int k,int l,int r,int L,int R,int v){
    if (r<L||R<l) return; 
    if (L<=l&&r<=R){
        le[k]=max(le[k],v);
        return;
    }
    pushdown_l(k);
    int mid=l+r>>1;
    add_l(k<<1,l,mid,L,R,v);
    add_l(k<<1|1,mid+1,r,L,R,v);
}
int get_l(int k,int l,int r,int p){
    if (l==r){
        return le[k];
    }
    pushdown_l(k);
    int mid=l+r>>1;
    if (p<=mid) return get_l(k<<1,l,mid,p); else return get_l(k<<1|1,mid+1,r,p);
}

//线段树求解右区间 

void pushdown_r(int k){
    if (ri[k]==n+1) return;
    ri[k<<1]=min(ri[k<<1],ri[k]);
    ri[k<<1|1]=min(ri[k<<1|1],ri[k]);
}
void add_r(int k,int l,int r,int L,int R,int v){
    if (r<L||R<l) return;
    if (L<=l&&r<=R){
        ri[k]=min(ri[k],v);
        return;
    }
    pushdown_r(k);
    int mid=l+r>>1;
    add_r(k<<1,l,mid,L,R,v);
    add_r(k<<1|1,mid+1,r,L,R,v);
}
int get_r(int k,int l,int r,int p){
    if (l==r){
        return ri[k];
    }
    pushdown_r(k);
    int mid=l+r>>1;
    if (p<=mid) return get_r(k<<1,l,mid,p); else return get_r(k<<1|1,mid+1,r,p);
}

//用线段树标记不同的 Bessie 值(即 f 数组)( 1 表示 HI,0 表示 LO,2 表示下辖区块可能 HI,也可能 LO) 

void build(int k,int l,int r){
    if (l==r){
        f[k]=2;
        h[l]=k;//为方便输出,用 h 数组记得 l 的节点值为 k 
        return;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    f[k]=2;
}

//更新 k 节点的值为 v 

void count(int k,int v){
    if (v==2) return;
    if (f[k]==1&&v==0){
        f[k]=v;
        cnt[k]++; 
    } else f[k]=v;
}

// f 上放 

void pushup(int k){
    if (f[k<<1]==2||f[k<<1|1]==2){
        f[k]=2;
    } else if (f[k<<1]!=f[k<<1|1]){
        f[k]=2;
    } else if (f[k<<1]==f[k<<1|1]){
        f[k]=f[k<<1];
        f[k<<1]=f[k<<1|1]=2;//当子节点值相同时,防止重复计算,子节点赋值为不确定
    }
}

// f 、懒标记下放 

void pushdown(int k){
    count(k<<1,f[k]);
    cnt[k<<1]+=cnt[k];
    count(k<<1|1,f[k]);
    cnt[k<<1|1]+=cnt[k];
    cnt[k]=0;
}

//更改区间值为 v 

void change(int k,int l,int r,int L,int R,int v){
    if (r<L||R<l) return;
    if (L<=l&&r<=R){
        count(k,v);
        return; 
    }
    pushdown(k);
    int mid=l+r>>1;
    change(k<<1,l,mid,L,R,v);
    change(k<<1|1,mid+1,r,L,R,v);
    pushup(k);
}

//将所有 f 、懒标记的值下放 

void query(int k,int l,int r){
    if (l==r) return;
    pushdown(k);
    int mid=l+r>>1;
    query(k<<1,l,mid);
    query(k<<1|1,mid+1,r);
}



int main(){
    scanf("%d",&n);

    //左右区间初始化 

    for (int i=1;i<=4*n;i++) {
        le[i]=0;
        ri[i]=n+1;
    }
    build(1,0,n);//构造线段树 
    for (int i=1;i<=n;i++){
        int p;
        scanf("%d",&p);
        int x=get_l(1,1,n,p),y=get_r(1,1,n,p);//取出每个值对应的左右区间
        change(1,0,n,x,p-1,1);//对于 left ~ p 标记 HI 
        change(1,0,n,p,y-1,0);//对于 p ~ right 标记 LO 
        add_l(1,1,n,p+1,n,p);//把 p 加入 p 右边的左区间计算中 
        add_r(1,1,n,1,p-1,p);//把 p 加入 p 左边的右区间计算中 
    }
    query(1,0,n);//把所有懒标记下方

    //输出 

    for (int i=0;i<=n;i++)
        printf("%d\n",cnt[h[i]]);
    return 0;
}

评论

caxx_shaozenan
dfdf_xuziye
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ljxx_xuzihan
stO % Orz
syyx_zhangshihao
orz&&qp
dfdj_loushuhao
%%%