《分块总结》

无语,调试的煎熬..

数列分块入门 9

求区间的最小的出现最多次数的数。

这里很显然先处理出块与块之间的最小众数,然后两边的残余块暴力就行。

如何高效找两边的,这里就用到了二分,首先要对数离散化,然后值的容器里存位置,然后直接用查询的区间去二分,这样就能找到给定的区间里有多少个了。

PS:预处理写错了找了好久。。一开始写到了if里面,后面发现这样有的块就更新不到了。~~

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int N = 1e5 + 5;
const int M = 2000 + 5;
const LL Mod = 10007;
#define pi acos(-1)
#define INF 1e18 + 5
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO {
inline int read() {
    int x = 0, f = 1;
    char c = getchar();

    while (c < '0' || c > '9') {
        if (c == '-')
            f = -1;

        c = getchar();
    }

    while (c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }

    return x * f;
}
}
using namespace FASTIO;

int n, sz, bl[N], a[N], b[N], len;
int mx[M][M], mxnum[M][M], num[N], mp[N];
bool vis[N];
vector<int> vec[N];
void init(int x) {
    for(int i = 1;i <= len;++i) num[i] = 0;
    int maxx = 0, mxpos = 0;

    for (int i = (x - 1) * sz + 1; i <= n; ++i) {
        num[a[i]]++;
        if (num[a[i]] > maxx || (num[a[i]] == maxx && a[i] < mxpos)) {
            maxx = num[a[i]];
            mxpos = a[i];
        }
        mx[x][bl[i]] = mxpos;
        mxnum[x][bl[i]] = maxx;
    }
}

int query(int L, int r) {
    int maxx = 0, mxpos = 0;

    for (int i = 1; i <= len; ++i)
        num[i] = vis[i] = 0;

    if (bl[L] + 1 <= bl[r] - 1) {
        maxx = mxnum[bl[L] + 1][bl[r] - 1];
        mxpos = mx[bl[L] + 1][bl[r] - 1];
    }

    for (int i = L; i <= min(n, bl[L] * sz); ++i) {
        if (vis[a[i]] == 0) {
            int pos2 = upper_bound(vec[a[i]].begin(), vec[a[i]].end(), r) - vec[a[i]].begin();
            int pos1 = lower_bound(vec[a[i]].begin(), vec[a[i]].end(), L) - vec[a[i]].begin();
            num[a[i]] = pos2 - pos1;
            vis[a[i]] = 1;
        }

        if (num[a[i]] > maxx || (num[a[i]] == maxx && a[i] < mxpos)) {
            maxx = num[a[i]];
            mxpos = a[i];
        }
    }

    if (bl[L] * sz + 1 > r)
        return mp[mxpos];

    for (int i = (bl[r] - 1) * sz + 1; i <= r; ++i) {
        if (vis[a[i]] == 0) {
            int pos2 = upper_bound(vec[a[i]].begin(), vec[a[i]].end(), r) - vec[a[i]].begin();
            int pos1 = lower_bound(vec[a[i]].begin(), vec[a[i]].end(), L) - vec[a[i]].begin();
            num[a[i]] = pos2 - pos1;
            vis[a[i]] = 1;
        }

        if (num[a[i]] > maxx || (num[a[i]] == maxx && a[i] < mxpos)) {
            maxx = num[a[i]];
            mxpos = a[i];
        }
    }

    return mp[mxpos];
}

int main() {
    n = read();
    //sz = sqrt(n);
    sz = 150;
    int tot = 0;

    for (int i = 1; i <= n; ++i) {
        a[i] = read();
        b[++tot] = a[i];
    }

    sort(b + 1, b + tot + 1);
    len = unique(b + 1, b + tot + 1) - b - 1;

    for (int i = 1; i <= n; ++i) {
        int x = lower_bound(b + 1, b + len + 1, a[i]) - b;
        mp[x] = a[i];
        a[i] = x;
    }

    for (int i = 1; i <= n; ++i) {
        bl[i] = (i - 1) / sz + 1;
        vec[a[i]].push_back(i);
    }

    for (int i = 1; i <= n / sz + 1; ++i) {
        init(i);
    }

    for (int i = 1; i <= n; ++i) {
        int L, r;
        L = read(), r = read();
        printf("%d
", query(L, r));
    }

    return 0;
}
/*
12
10 9 23 45 31 44 44 23 9 5 6 6
1 2
1 3
1 4
1 5
1 6
1 7
1 8

*/
View Code

数列分块入门 8

查找区间某个数出现的次数并修改,这里其实是偏暴力的做法,因为最多标记一次之后就很快了。

一开始一直觉得会超时,这种复杂度好难估算啊~。。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int N = 1e5 + 5;
const int M = 1e3;
const LL Mod = 10007;
#define pi acos(-1)
#define INF 1e18 + 5
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO {
inline int read() {
    int x = 0, f = 1;
    char c = getchar();

    while (c < '0' || c > '9') {
        if (c == '-')
            f = -1;

        c = getchar();
    }

    while (c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }

    return x * f;
}
}
using namespace FASTIO;

int n, sz, bl[N], num[N], a[N];

int solve(int L, int r, int c) {
    int ans = 0;
    int st = (bl[L] - 1) * sz + 1;
    int ed = min(n, bl[L] * sz);

    if (num[bl[L]] != 0) {
        for (int i = st; i <= ed; ++i)
            a[i] = num[bl[L]];

        num[bl[L]] = 0;
    }

    for (int i = L; i <= min(bl[L] * sz, r); ++i) {
        if (a[i] == c)
            ans++;

        a[i] = c;
    }

    L = bl[L] * sz + 1;

    if (L > r)
        return ans;

    while (bl[L] != bl[r]) {
        if (num[bl[L]] != 0) {
            if (num[bl[L]] == c) {
                int st = (bl[L] - 1) * sz + 1;
                int ed = min(n, bl[L] * sz);
                ans += ed - st + 1;
            }
        } else {
            int st = (bl[L] - 1) * sz + 1;
            int ed = bl[L] * sz;

            for (int j = st; j <= ed; ++j) {
                if (a[j] == c)
                    ans++;
            }
        }

        num[bl[L]] = c;
        L = bl[L] * sz + 1;
    }

    st = (bl[L] - 1) * sz + 1;
    ed = min(n, bl[L] * sz);

    if (num[bl[L]] != 0) {
        for (int i = st; i <= ed; ++i)
            a[i] = num[bl[L]];

        num[bl[L]] = 0;
    }

    for (int i = L; i <= r; ++i) {
        if (a[i] == c)
            ans++;

        a[i] = c;
    }

    return ans;
}

int main() {
    n = read();
    sz = sqrt(n);

    for (int i = 1; i <= n; ++i)
        a[i] = read();

    for (int i = 1; i <= n; ++i) {
        bl[i] = (i - 1) / sz + 1;
    }

    for (int i = 1; i <= n; ++i) {
        int L, r, c;
        L = read(), r = read(), c = read();
        printf("%d
", solve(L, r, c));
    }

    return 0;
}
View Code

数列分块入门 7

区间加乘,注意顺序的处理即可,想清楚其实不难。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int N = 1e5 + 5;
const int M = 1e3;
const LL Mod = 10007;
#define pi acos(-1)
#define INF 1e18 + 5
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO {
inline LL read() {
    LL x = 0, f = 1;
    char c = getchar();

    while (c < '0' || c > '9') {
        if (c == '-')
            f = -1;

        c = getchar();
    }

    while (c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }

    return x * f;
}
}
using namespace FASTIO;

int n, sz, bl[N];
LL ADD[N], MUL[N], Size[N], a[N], link[M][M], pla[N];

void add(int L, int r, int c) {
    int st = (bl[L] - 1) * sz + 1;
    int ed = min(n, bl[L] * sz);

    for (int i = st; i <= ed; ++i) {
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] * MUL[bl[L]]) % Mod;
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] + ADD[bl[L]]) % Mod;
    }

    MUL[bl[L]] = 1;
    ADD[bl[L]] = 0;

    for (int i = L; i <= min(bl[L] * sz, r); ++i) {
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] + c) % Mod;
    }

    L = bl[L] * sz + 1;

    if (L > r)
        return ;

    while (bl[L] != bl[r]) {
        ADD[bl[L]] = (ADD[bl[L]] + c) % Mod;
        L = bl[L] * sz + 1;
    }

    st = (bl[L] - 1) * sz + 1;
    ed = min(n, bl[L] * sz);

    for (int i = st; i <= ed; ++i) {
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] * MUL[bl[L]]) % Mod;
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] + ADD[bl[L]]) % Mod;
    }

    MUL[bl[L]] = 1;
    ADD[bl[L]] = 0;

    for (int i = L; i <= r; ++i) {
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] + c) % Mod;
    }

}

void mul(int L, int r, int c) {
    int st = (bl[L] - 1) * sz + 1;
    int ed = min(n, bl[L] * sz);

    for (int i = st; i <= ed; ++i) {
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] * MUL[bl[L]]) % Mod;
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] + ADD[bl[L]]) % Mod;
    }

    MUL[bl[L]] = 1;
    ADD[bl[L]] = 0;

    for (int i = L; i <= min(bl[L] * sz, r); ++i) {
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] * c) % Mod;
    }

    L = bl[L] * sz + 1;

    if (L > r)
        return ;

    while (bl[L] != bl[r]) {
        MUL[bl[L]] = (MUL[bl[L]] * c) % Mod;
        ADD[bl[L]] = (ADD[bl[L]] * c) % Mod;
        L = bl[L] * sz + 1;
    }

    st = (bl[L] - 1) * sz + 1;
    ed = min(n, bl[L] * sz);

    for (int i = st; i <= ed; ++i) {
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] * MUL[bl[L]]) % Mod;
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] + ADD[bl[L]]) % Mod;
    }

    MUL[bl[L]] = 1;
    ADD[bl[L]] = 0;

    for (int i = L; i <= r; ++i) {
        link[bl[L]][pla[i]] = (link[bl[L]][pla[i]] * c) % Mod;
    }
}

LL query(int pos) {
    int sum = 0, st = 1;

    while (st != 0) {
        int ma = sum + Size[st];

        if (ma >= pos) {
            int tmp = pos - sum;
            //printf("mul is %lld add is %lld
",MUL[st],ADD[st]);
            return (link[st][tmp] * MUL[st] % Mod + ADD[st]) % Mod;
        }

        sum += Size[st];
        st++;
    }
}

int main() {
    n = read();
    sz = sqrt(n);

    for (int i = 1; i <= n; ++i)
        a[i] = read();

    for (int i = 1; i <= n; ++i) {
        bl[i] = (i - 1) / sz + 1;
        link[bl[i]][++Size[bl[i]]] = a[i];
        pla[i] = Size[bl[i]];
        MUL[bl[i]] = 1;
    }

    for (int i = 1; i <= n; ++i) {
        int opt, L, r, c;
        opt = read(), L = read(), r = read(), c = read();

        if (opt == 0)
            add(L, r, c);
        else if (opt == 1)
            mul(L, r, c);
        else
            printf("%lld
", query(r));

    }

    return 0;
}
/*
7
1 2 2 3 9 3 2
0 1 3 1
1 1 4 4
0 1 7 2
2 1 6 6
1 2 6 4
2 1 6 6

*/
View Code
原文地址:https://www.cnblogs.com/zwjzwj/p/14742349.html