LOJ #6279. 数列分块入门 3

 

 

 根据分块的思想,对于不整块的我们直接暴力统计,但是对于整块的,我们可以对每一块进行一个排序,利用二分查找找出最大的小于 c 的数,然后重复此操作即可

const int N=1e5+5;

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

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

void renew(int fa)
{
    int l=L[fa],r=R[fa];
    for(int i=l;i<=r;i++) b[i]=a[i];
    sort(b+l,b+r+1);
}

void update(int l,int r,int w)
{
    int st=bel[l],en=bel[r];
    if(st==en){
        for(int i=l;i<=r;i++) a[i]+=w;
        renew(st);
    } else{
        for(int i=l;i<=R[st];i++) a[i]+=w;
        renew(st);
        for(int i=L[en];i<=r;i++) a[i]+=w;
        renew(en);
        for(int i=st+1;i<=en-1;i++) tag[i]+=w;
    }
}

int query(int l,int r,int w)
{
    int ans=-1;
    int st=bel[l],en=bel[r];
    int tmp;
    if(st==en){
        for(int i=l;i<=r;i++){
            tmp=a[i]+tag[st];
            if(tmp>ans && tmp<w) ans=tmp;
        }
    } else{
        for(int i=l;i<=R[st];i++){
            tmp=a[i]+tag[st];
            if(tmp>ans && tmp<w) ans=tmp;
        }
        for(int i=L[en];i<=r;i++){
            tmp=a[i]+tag[en];
            if(tmp>ans && tmp<w) ans=tmp;
        }
        for(int i=st+1;i<=en-1;i++){
            int pos=lower_bound(b+L[i],b+R[i]+1,w-tag[i])-b-1;
            tmp=b[pos]+tag[i];
            if(tmp>ans && tmp<w) ans=tmp;
        }
    }
    return ans;
}

int main()
{
    //IOS;
    while(~sd(n)){
        for(int i=1;i<=n;i++) sd(a[i]);
        build();
        while(n--){
            int opt=read(),x=read(),y=read(),w=read();
            if(opt) pd(query(x,y,w));
            else update(x,y,w);
        }
    }
    //PAUSE;
    return 0;
}

 

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