zoukankan      html  css  js  c++  java
  • 《分块总结》

    无语,调试的煎熬..

    数列分块入门 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
  • 相关阅读:
    Two Sum II
    Subarray Sum
    Intersection of Two Arrays
    Reorder List
    Convert Sorted List to Binary Search Tree
    Remove Duplicates from Sorted List II
    Partition List
    Linked List Cycle II
    Sort List
    struts2结果跳转和参数获取
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/14742349.html
Copyright © 2011-2022 走看看