• bzoj2821 作诗(Poetize)


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2821

    【题解】

    今天看了黄学长的分块专项 感觉十分科学就来刚刚分块了。

    这题我们套用区间众数的办法。令f[i,j]表示i块到j块的答案,g[i,j]表示1...i块,数字为j的有多少个。

    然后我们大区间个数可以直接调用,两边暴力做。

    注意清零问题不能出现复杂度退化。

    有两种办法,一个是把所有即将出现的数的位置都清空或赋值,一种是排序后,找到第一个的时候赋值,后面累加。

    后面那个是popoqqq大爷写的(似乎强行多了个log)

    事实证明这个log很慢的。。

    大概……也就两倍把

    两份代码:

    O(n根号n)

    # include <stdio.h>
    # include <string.h>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 1e5 + 10, N = 320, BLOCK = 350;
    
    # define RG register
    # define ST static
    
    int n, C, q, B;
    int a[M], bl[M];
    int bst[N], bnd[N];
    int t[M];
    int f[N][N];
    int g[N][M];
    // 1..i block j appear ? time
    
    inline void prepare(int x) {
        int cur = 0, tem = x;
        memset(t, 0, sizeof t);
        for (int i=bst[x]; i<=n; ++i) {
            ++t[a[i]];
            if(t[a[i]]&1) {
                if(t[a[i]] == 1);
                else --cur;
            } else ++cur;
            if(bnd[tem] == i) {
                f[x][tem] = cur;
                ++tem;
            }
        }
    }
    
    int main() {
        scanf("%d%d%d", &n, &C, &q);
        for (int i=1; i<=n; ++i) {
            scanf("%d", a+i);
            bl[i] = (i-1)/BLOCK+1;
        }
        B = bl[n];
        for (int i=1; i<=B; ++i) bst[i] = (i-1)*BLOCK+1, bnd[i] = min(n, i*BLOCK);
        for (int i=1; i<=B; ++i) prepare(i);
        for (int i=1; i<=B; ++i) {
            for (int j=1; j<=C; ++j) g[i][j] = g[i-1][j];
            for (int j=bst[i]; j<=bnd[i]; ++j) g[i][a[j]] ++;
        }
        int l, r, lst=0;
        while(q--) {
            scanf("%d%d", &l, &r);
            l = (l+lst)%n+1, r = (r+lst)%n+1;
            if(l>r) swap(l, r);
    //        printf("%d %d
    ", l, r);
            if(bl[l] == bl[r]) {
                int cur = 0;
                for (int i=l; i<=r; ++i) t[a[i]] = 0;
                for (int i=l; i<=r; ++i) {
                    ++t[a[i]];
                    if(t[a[i]]&1) {
                        if(t[a[i]] == 1);
                        else --cur;
                    } else ++cur;
                }
                printf("%d
    ", lst = cur);
                continue;
            } 
            int cur = 0;
            if(bl[r]-bl[l] != 1) cur = f[bl[l]+1][bl[r]-1];
            for (int i=l; i<=bnd[bl[l]]; ++i) t[a[i]] = g[bl[r]-1][a[i]] - g[bl[l]][a[i]];
            for (int i=bst[bl[r]]; i<=r; ++i) t[a[i]] = g[bl[r]-1][a[i]] - g[bl[l]][a[i]];
            for (int i=l; i<=bnd[bl[l]]; ++i) {
                int x = a[i];
                ++t[x];
                if(t[x]&1) {
                    if(t[x] == 1);
                    else --cur;
                } else ++cur;
            }
            for (int i=bst[bl[r]]; i<=r; ++i) {
                int x = a[i];
                ++t[x];
                if(t[x]&1) {
                    if(t[x] == 1);
                    else --cur;
                } else ++cur;
            } 
            printf("%d
    ", lst = cur);
        }
        
        return 0;
    }
    View Code

    O(n根号nlogn)

    # include <stdio.h>
    # include <string.h>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 1e5 + 10, N = 320, BLOCK = 350;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, C, q, B;
    int a[M], bl[M];
    int bst[N], bnd[N];
    int t[M], tt[M], tn=0;
    int f[N][N];
    int g[N][M];
    // 1..i block j appear ? time
    
    inline void prepare(int x) {
        int cur = 0, tem = x;
        for (int i=bst[x]; i<=n; ++i) {
            ++t[a[i]];
            if(t[a[i]]&1) {
                if(t[a[i]] == 1);
                else --cur;
            } else ++cur;
            if(bnd[tem] == i) {
                f[x][tem] = cur;
                ++tem;
            }
        }
        memset(t, 0, sizeof t);
    }
    
    int main() {
        scanf("%d%d%d", &n, &C, &q);
        for (int i=1; i<=n; ++i) {
            scanf("%d", a+i);
            bl[i] = (i-1)/BLOCK+1;
        }
        B = bl[n];
        for (int i=1; i<=B; ++i) bst[i] = (i-1)*BLOCK+1, bnd[i] = min(n, i*BLOCK);
        for (int i=1; i<=B; ++i) prepare(i);
        for (int i=1; i<=n; ++i) g[bl[i]][a[i]]++;
        for (int i=1; i<=B; ++i)
            for (int j=1; j<=C; ++j)
                g[i][j] += g[i-1][j];
        int l, r, lst=0;
        while(q--) {
            scanf("%d%d", &l, &r);
            l = (l+lst)%n+1, r = (r+lst)%n+1;
            if(l>r) swap(l, r);
    //        printf("%d %d
    ", l, r);
            if(bl[l] == bl[r]) {
                int cur = 0;
                for (int i=l; i<=r; ++i) {
                    ++t[a[i]];
                    if(t[a[i]]&1) {
                        if(t[a[i]] == 1);
                        else --cur;
                    } else ++cur;
                }
                printf("%d
    ", lst = cur);
                for (int i=l; i<=r; ++i) --t[a[i]];
                continue;
            } 
            tn = 0;
            int cur = 0;
            if(bl[r]-bl[l] != 1) cur = f[bl[l]+1][bl[r]-1];
            for (int i=l; i<=bnd[bl[l]]; ++i) tt[++tn] = a[i];
            for (int i=bst[bl[r]]; i<=r; ++i) tt[++tn] = a[i];
            sort(tt+1, tt+tn+1);
    //        for (int i=1; i<=tn; ++i) printf("%d ", tt[i]);
    //        puts("
    =====");
            for (int i=1; i<=tn; ++i) {
                int x = tt[i];
                if(tt[i] != tt[i-1]) t[x] = g[bl[r]-1][x]-g[bl[l]][x];
                ++t[x];
                if(t[x]&1) {
                    if(t[x] == 1);
                    else --cur;
                } else ++cur;
            }
            printf("%d
    ", lst = cur);
            for (int i=1; i<=tn; ++i) t[tt[i]] = 0;
        }
        
        return 0;
    }
    View Code
  • 相关阅读:
    深入理解DB2缓冲池(BufferPool)
    收银台采坑总结
    webpack4的总结
    无心法师-讲解
    cache 缓存的处理
    用es6方式的写的订阅发布的模式
    Skeleton Screen -- 骨架屏--应用
    promise实现原理
    业务线移动端适配方案总结
    vdom,diff,key 算法的了解
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj2821.html
Copyright © 2020-2023  润新知