分块入门 LOJ

本文是关于LOJ平台上的分块技术入门教程,详细介绍了分块的基础概念和应用场景,包括7个部分逐步解析分块入门知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LOJ  分块入门:

 

1. 分块入门 1

#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + 100;
int n, blo, a[N], b[N], tag[N];
void modify(int l, int r, int c) {
    for (int i = l; i <= min(r, b[l]*blo); ++i)
        a[i] += c;
    if (b[l] != b[r])
        for (int i = (b[r] - 1) * blo + 1; i <= r; ++i)
            a[i] += c;
    for (int i = b[l] + 1; i <= b[r] - 1; ++i)
        tag[i] += c;
}
int main() {
    int opt, l, r, c;
    scanf("%d", &n);
    blo = sqrt(n);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);
    for (int i = 1; i <= n; ++i)
        b[i] = (i - 1) / blo + 1;

    for (int i = 0; i < n; ++i) {
        scanf("%d%d%d%d", &opt, &l, &r, &c);
        if (opt == 0) {
            modify(l, r, c);
        } else {
            printf("%d\n", a[r] + tag[b[r]]);
        }
    }

    return 0;
}

1. 分块入门2

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100;
int n, m, blo, bl[N], a[N], tag[N], id[N];
int ans;
vector<int>vec[510];
void reset(int x) {
    vec[x].clear();
    for (int i = (x - 1) * blo + 1; i <= min(x * blo, n); ++i)
        vec[x].push_back(a[i]);
    sort(vec[x].begin(), vec[x].end());
}

void modify(int x, int y, int z) {
    for (int i = x; i <= min(y, bl[x]*blo); ++i)
        a[i] += z;
    reset(bl[x]);
    if (bl[x] != bl[y]) {
        for (int i = (bl[y] - 1) * blo + 1; i <= y; ++i)
            a[i] += z;
        reset(bl[y]);
    }
    for (int i = bl[x] + 1; i <= bl[y] - 1; ++i)
        tag[i] += z;
}

int query(int x, int y, int z) {
    int ans = 0;
    for (int i = x; i <= min(y, (bl[x]*blo)); ++i)
        if (a[i] + tag[bl[x]] < z) ans++;
    if (bl[x] != bl[y])
        for (int i = (bl[y] - 1) * blo + 1; i <= y; ++i)
            if (a[i] + tag[bl[y]] < z) ans++;

    for (int i = bl[x] + 1; i <= bl[y] - 1; ++i) {
        ans += lower_bound(vec[i].begin(), vec[i].end(), z - tag[i]) - vec[i].begin();
    }
    return ans;
}
int main() {
    int opt, x, y, z;
    scanf("%d", &n);
    blo = sqrt(n);   //这个是每块的个数,并不是块数.
    for (int i = 1; i <= n; ++i) bl[i] = (i - 1) / blo + 1;
    for (int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);
    for (int i = 1; i <= bl[n]; ++i)
        reset(i);
    for (int i = 0; i < n; ++i) {
        scanf("%d%d%d%d", &opt, &x, &y, &z);
        if (opt == 0) {
            modify(x, y, z);
        } else {
            printf("%d\n", query(x, y, z * z));
        }
    }
    return 0;
}

3. 分块入门

#include<bits/stdc++.h>
using namespace std;
ll read() {
    ll x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-')f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
int n, blo;
int v[100005], bl[100005], atag[100005];
set<int>st[105];
void add(int a, int b, int c) {
    for(int i = a; i <= min(bl[a]*blo, b); i++) {
        st[bl[a]].erase(v[i]);
        v[i] += c;
        st[bl[a]].insert(v[i]);
    }
    if(bl[a] != bl[b]) {
        for(int i = (bl[b] - 1) * blo + 1; i <= b; i++) {
            st[bl[b]].erase(v[i]);
            v[i] += c;
            st[bl[b]].insert(v[i]);
        }
    }
    for(int i = bl[a] + 1; i <= bl[b] - 1; i++)
        atag[i] += c;
}
int query(int a, int b, int c) {
    int ans = -1;
    for(int i = a; i <= min(bl[a]*blo, b); i++) {
        int val = v[i] + atag[bl[a]];
        if(val < c)ans = max(val, ans);
    }
    if(bl[a] != bl[b])
        for(int i = (bl[b] - 1) * blo + 1; i <= b; i++) {
            int val = v[i] + atag[bl[b]];
            if(val < c)ans = max(val, ans);
        }
    for(int i = bl[a] + 1; i <= bl[b] - 1; i++) {
        int x = c - atag[i];
        set<int>::iterator it = st[i].lower_bound(x);
        if(it == st[i].begin())continue;
        --it;
        ans = max(ans, *it + atag[i]);
    }
    return ans;
}
int main() {
    n = read();
    blo = 1000;
    for(int i = 1; i <= n; i++)v[i] = read();
    for(int i = 1; i <= n; i++) {
        bl[i] = (i - 1) / blo + 1;
        st[bl[i]].insert(v[i]);
    }
    for(int i = 1; i <= n; i++) {
        int f = read(), a = read(), b = read(), c = read();
        if(f == 0)add(a, b, c);
        if(f == 1)printf("%d\n", query(a, b, c));
    }
    return 0;
}

 

4.分块入门

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100;
int b[N], blo;
long long tag[N], a[N], sum[N];
int n, m;
void modify(int x, int y, int z) {
    for (int i = x; i <= min(y, b[x] * blo); ++i) {
        a[i] += z;
        sum[b[x]] += z;
    }
    if (b[x] != b[y])
        for (int i = (b[y] - 1) * blo + 1; i <= y; ++i) {
            a[i] += z;
            sum[b[y]] += z;
        }
    for (int i = b[x] + 1; i <= b[y] - 1; ++i) tag[i] += z;
}

long long query(int x, int y, int z) {
    long long ans = 0;
    for (int i = x; i <= min(y, b[x] * blo); ++i) ans = (ans + a[i] + tag[b[x]]) % z;
    if (b[x] != b[y])
        for (int i = (b[y] - 1) * blo + 1; i <= y; ++i) ans = (ans + a[i] + tag[b[y]]) % z;
    for (int i = b[x] + 1; i <= b[y] - 1; ++i) ans = ans + sum[i] + tag[i] * blo;
    return ans % z;
}
int main() {
    int op, x, y, z;
    scanf("%d", &n);
    blo = sqrt(n);
    for (int i = 1; i <= n; ++i) {
        scanf("%lld", &a[i]);
        b[i] = (i - 1) / blo + 1;
        sum[b[i]] += a[i];
    }
    for (int i = 0; i < n; ++i) {
        scanf("%d%d%d%d", &op, &x, &y, &z);
        if (op == 0)
            modify(x, y, z);
        if (op == 1)
            printf("%lld\n", query(x, y, z + 1));
    }
    return 0;
}

5.分块入门

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100;
int a[N], blo, b[N], n, m;
long long sum[N];
void sovle(int x) {
    if (sum[x] == blo) return;
    sum[x] = 0;
    for (int i = (x - 1) * blo + 1; i <= x*blo; ++i) {
        a[i] = sqrt(a[i]), sum[x] += a[i];
    }
}
void modify(int x, int y, int z) {
    for (int i = x; i <= min(y, b[x]*blo); ++i) {
        sum[b[x]] -= a[i];
        a[i] = sqrt(a[i]);
        sum[b[x]] += a[i];
    }
    if (b[x] != b[y])
        for (int i = (b[y] - 1) * blo + 1; i <= y; ++i) {
            sum[b[y]] -= a[i];
            a[i] = sqrt(a[i]);
            sum[b[y]] += a[i];
        }
    for (int i = b[x] + 1; i <= b[y] - 1; ++i)
        sovle(i);
}

long long query(int x, int y, int z) {
    long long ans = 0;
    for (int i = x; i <= min(y, b[x]*blo); ++i)
        ans += a[i];
    if (b[x] != b[y])
        for (int i = (b[y] - 1) * blo + 1; i <= y; ++i)
            ans += a[i];
    for (int i = b[x] + 1; i <= b[y] - 1; ++i)
        ans += sum[i];
    return ans;
}
int main() {
    int op, x, y, z;
    scanf("%d", &n);
    blo = sqrt(n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        b[i] = (i - 1) / blo + 1;
        sum[b[i]] += a[i];
    }
    for (int i = 0; i < n; ++i) {
        scanf("%d%d%d%d", &op, &x, &y, &z);
        if (op == 0) modify(x, y, z);
        if (op == 1) printf("%lld\n", query(x, y, z));
    }

    return 0;
}

6.分块入门

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 100;
typedef pair<int, int> P;
int n, m, blo, a[N], b[N << 1], tp;
vector<int>v[5000];
pair<int, int> query(int x) {
    for (int i = 1; i <= m; ++i)
        if(x > v[i].size()) x -= v[i].size();
        else {
            return P(i, x - 1);
        }
}
void rebuild() {
    tp = 0;
    for (int i = 1; i <= m; ++i) {
        int len = v[i].size();
        for (int j = 0; j < len; ++j)
            b[++tp] = v[i][j];
        v[i].clear();
    }
    int  blo1 = sqrt(tp);
    m = (tp - 1) / blo1 + 1;
    for (int i = 1; i <= tp; ++i)
        v[(i - 1) / blo1 + 1].push_back(b[i]);
}
void modify(int x, int y, int z) {
    P t = query(x);
    v[t.first].insert(v[t.first].begin() + t.second, y);
    if (v[t.first].size() > 20 * blo) rebuild();
}

int main() {
    int op, x, y, z;
    scanf("%d", &n);
    blo = sqrt(n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        v[(i - 1) / blo + 1].push_back(a[i]);
    }
    m = (n - 1) / blo + 1;
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d%d%d", &op, &x, &y, &z);
        if(op == 0) modify(x, y, z);
        if(op == 1) {
            P t = query(y);
            printf("%d\n", v[t.first][t.second]);
        }
    }

    return 0;
}

7.分块入门

#include<bits/stdc++.h>
using namespace std;
const int  N = 1e5+100;
const int mod = 10007;
int blo, b[N],n;
long long mul[N],add[N],sum[N],a[N];

void modify(int x, int y, int mm, int aa){
    for (int i = (b[x] - 1) * blo + 1; i <= b[x]*blo; ++i)
        a[i] = (a[i]*mul[b[x]] + add[b[x]]) % mod;
    mul[b[x]] = 1; add[b[x]] = 0;
    for (int i = x; i <= min(y, b[x]*blo); ++i)
        a[i] = (a[i]*mm + aa) % mod;

    if (b[x] != b[y]){
        for (int i = (b[y]-1)*blo + 1; i <= b[y]*blo; ++i)
            a[i] = (a[i]*mul[b[y]] + add[b[y]]) % mod;
         mul[b[y]] = 1, add[b[y]] = 0;
        for (int i = (b[y]-1)*blo + 1; i <= y; ++i)
            a[i] = (a[i] * mm + aa)  % mod;
    }

    for (int i = b[x] + 1; i <= b[y] -1; ++i){
        mul[i] = (mul[i] * mm) % mod;
        add[i] = (add[i] * mm + aa) % mod;
    }
}
long long query(int x){
    return (1ll*a[x] * mul[b[x]] + add[b[x]])%mod;
}

int main(){
    int op,x,y,z;
    scanf("%d",&n);
    blo = sqrt(n);
    for (int i = 1; i <= n; ++i){
        scanf("%lld",&a[i]);
        b[i] = (i - 1)/ blo + 1;
        mul[i] = 1;
    }
    for (int i = 0; i < n; ++i){
        scanf("%d%d%d%d",&op, &x,&y,&z);
        if (op == 0) modify(x,y,1,z);
        if (op == 1) modify(x,y,z,0);
        if (op == 2) printf("%lld\n",query(y));
    }
    return 0;
}

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值