LOJ #6284. 数列分块入门 8

 

 

设置一个数组维护一个块内所有的数是否相等,若全部等于 x,则将数组标记为 x,这样在处理整块的数组时,只有 tag[]=-1 时需要操作,对于不是整块的暴力即可

const int N=1e5+5;

    int i,j,k;
    int n,m,t;
    int a[N];
    int bel[N],num,block;
    int L[N],R[N],tag[N];

void build()
{
    block=sqrt(n);
    num=n/block; if(n%block) num++;
    for(int i=1;i<=num;i++){
        int l=(i-1)*block+1;
        int r=min(i*block,n);
        R[i]=r; L[i]=l; tag[i]=a[l];
        for(int j=l;j<=r;j++){
            bel[j]=i;
            if(a[l]!=a[j]) tag[i]=-1;
        }
    }
}

void push_down(int x)
{
    int l=L[x],r=R[x];
    for(int i=l;i<=r;i++) a[i]=tag[x];
}

void update(int x)
{
    int l=L[x],r=R[x];
    tag[x]=-1;
    for(int i=l+1;i<=r;i++){
        if(a[l]!=a[i]) return ;
    }
    tag[x]=a[l];
}

int ask(int l,int r,int w)
{
    int ans=0;
    int st=bel[l],en=bel[r];
    if(st==en){
        if(tag[st]!=-1) push_down(st);
        for(int i=l;i<=r;i++){
            if(a[i]==w) ans++;
            else a[i]=w;
        }
        update(st);
    } else{
        if(tag[st]!=-1) push_down(st);
        for(int i=l;i<=R[st];i++){
            if(a[i]==w) ans++;
            else a[i]=w;
        }
        update(st);
        if(tag[en]!=-1) push_down(en);
        for(int i=L[en];i<=r;i++){
            if(a[i]==w) ans++;
            else a[i]=w;
        }
        update(en);
        for(int i=st+1;i<=en-1;i++){
            if(tag[i]==w) ans+=block;
            else if(tag[i]!=-1) tag[i]=w;
            else{
                for(int j=L[i];j<=R[i];j++){
                    if(a[j]==w) ans++;
                    else a[j]=w;
                }
                update(i);
            }
        }
    }
    return ans;
}

int main()
{
    //IOS;
    while(~sd(n)){
        for(int i=1;i<=n;i++) sd(a[i]);
        build();
        int l,r,w;
        while(n--){
            l=read(),r=read(),w=read();
            pd(ask(l,r,w));
        }
    }
    //PAUSE;
    return 0;
}

 

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页