[LOJ] 分块九题 8

区间查询数值+整体赋值

维护tag代表整个区间被赋成了tag[i]

pushdown操作,而不是修改了再check。

不压缩代码了,调起来心累,长点有啥不好。

//Stay foolish,stay hungry,stay young,stay simple
#include<iostream>
#include<cmath>
#include<cctype>
#include<cstdio> 
using namespace std;

inline int read_d(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c)) f=c=='-'?-1:1;
    while(isdigit(c)){
        ret=ret*10+c-'0';
        c=getchar();
    }
    return ret*f;
}

const int MAXN=500005;

int n;
int a[MAXN],l[MAXN],r[MAXN],tag[MAXN];
int bl[MAXN];
int num,block;

void pushdown(int id){
    if(tag[id]==-1) return;
    for(int i=l[id];i<=r[id];i++) a[i]=tag[id];
    tag[id]=-1;
}

void build(){
    block=sqrt(n);
    num=n/block;
    if(n%block) num++;
    for(int i=1;i<=n;i++){
        bl[i]=(i-1)/block+1;
    }
    for(int i=1;i<=num;i++){
        l[i]=(i-1)*block+1;
        r[i]=i*block;
        tag[i]=-1;
    }
    r[num]=n;
}

int query(int x,int y,int w){
    int ret=0;
    if(bl[x]==bl[y]){
        pushdown(bl[x]);
        for(int i=x;i<=y;i++) ret+=(a[i]==w),a[i]=w;
        return ret; 
    }
    pushdown(bl[x]);
    for(int i=x;i<=r[bl[x]];i++){
        ret+=(a[i]==w);a[i]=w;
    }
    pushdown(bl[y]);
    for(int i=l[bl[y]];i<=y;i++){
        ret+=(a[i]==w);a[i]=w;
    }
    for(int i=bl[x]+1;i<=bl[y]-1;i++){
        if(tag[i]==-1){
            for(int j=l[i];j<=r[i];j++){
                ret+=(a[j]==w);
                a[j]=w;
            }
            tag[i]=w;
            continue;
        }
        if(tag[i]==w){
            ret+=r[i]-l[i]+1;
        }else tag[i]=w;
    }
    return ret;
}

int main(){
    n=read_d();
    for(int i=1;i<=n;i++) a[i]=read_d();
    build();
    for(int i=1;i<=n;i++){
        int x=read_d(),y=read_d(),z=read_d();
        printf("%d\n",query(x,y,z));
    }
    return 0;
}
posted @ 2018-04-13 17:38  GhostCai  阅读(92)  评论(0编辑  收藏  举报