数列分块入门 3 题解

Posted lajiccf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数列分块入门 3 题解相关的知识,希望对你有一定的参考价值。

https://loj.ac/problem/6279

vector+块内二分。

修改时需要重构,查询时可以二分查出来。

不要忘记 add 标记!

#pragma GCC diagnostic error "-std=c++14"
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
int n,bl,m,opt,l,r,v;
int a[100010], pos[100010], add[100010],L[100010],R[100010];
vector<int> b[100010];
void reset(int x) {
    b[x].clear();
    for(int i=L[x]; i<=R[x]; i++)
        b[x].push_back(a[i]+=add[x]);
    sort(b[x].begin(),b[x].end());
    add[x]=0;
    return;
}//对第 x 块进行重构,并加上标记
void update(int l, int r, int v) {
    if(pos[l]==pos[r]) {
        for(int i=l; i<=r; i++)
            a[i]+=v;
        reset(pos[l]);
        return;
    }
    for(int i=l; i<=R[pos[l]]; i++)
        a[i]+=v;
    reset(pos[l]);
    for(int i=L[pos[r]]; i<=r; i++)
        a[i]+=v;
    reset(pos[r]);
    for(int i=pos[l]+1; i<=pos[r]-1; i++)
        add[i]+=v;
    return;
}
int query(int l, int r, int v) {
    int ans=-1;
    if(pos[l]==pos[r]) {
        for(int i=l; i<=r; i++)
            if(a[i]+add[pos[i]]<v)
                ans=max(ans,a[i]+add[pos[i]]);
        return ans;
    }
    for(int i=l;i<=R[pos[l]];i++)
        if(a[i]+add[pos[i]]<v)
            ans=max(ans,a[i]+add[pos[i]]);
    for(int i=L[pos[r]];i<=r;i++)
        if(a[i]+add[pos[i]]<v)
            ans=max(ans,a[i]+add[pos[i]]);
    for(int i=pos[l]+1;i<=pos[r]-1;i++) {
        int kk=lower_bound(b[i].begin(),b[i].end(),v-add[i])-b[i].begin();
        if(kk>0)
            ans=max(ans,b[i][kk-1]+add[i]);//二分查找
    }
    return ans;
}
int main() {
    scanf("%d", &n);
    bl = sqrt(n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        pos[i] = (i - 1) /bl + 1;
        b[pos[i]].push_back(a[i]);
    }
    for(int i=1; i<=pos[n]; i++)
        L[i]=(i-1)*bl+1,R[i]=i*bl;
    R[pos[n]]=n;
    for(int i=1; i<=pos[n]; i++)
        sort(b[i].begin(),b[i].end());
    for (int i = 1; i <= n; i++) {
        int ch;
        int x, y, v;
        scanf("%d %d %d %d", &ch, &x, &y, &v);
        if (ch == 0)
            update(x, y, v);
        else
            printf("%d
", query(x, y, v));
    }
    return 0;
}

以上是关于数列分块入门 3 题解的主要内容,如果未能解决你的问题,请参考以下文章

题解——loj6280 数列分块入门4 (分块)

『题解』LibreOJ6277 数列分块入门 1

LibreOJ 6278. 数列分块入门 2 题解

loj#6281. 数列分块入门 5

LiberOJ 6278 数列分块入门 2(分块)

数列分块入门3 解题报告