• Luogu 4135 作诗


    lyd大神犇的狗粮题……   

    终于填掉了这个大坑, 之前由于有一些事情一直没有想清楚, 一直没有动手写此题,就记录一下那些“有一些事情”
    1、对于对答案的贡献问题
    若要统计[l, r]中所有颜色的贡献:
    在扫描的过程中记录出现的次数cnt, 若cnt第一次变到2的时候, 把当前答案加一, 如果当前cnt大于二, 答案应当减一

    **简单分析:**当一个数第一次到达出现2次的时候,应当显然地对答案产生了贡献, 当这个数在第三次出现的时候, 它之前产生的贡献就被消除了, 第四次出现的时候就又会被累加回来, 所以这样是对的

    2、复杂度分析, 对于这样的块大小在块内不套log的情况下应当是取sqrt(n) 最优 (然而可能我太蒟了, 跑得很卡)

    3、一开始犯了一个脑残的错误

    pos[x] + 1 <= pos[y]

    分分钟跑成暴力……

    Code:

    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    const int N = 1e5 + 5;
    const int B = 320;
    
    int n, m, c, bnum, a[N], l[B], r[B], pos[N];
    int sum[B][N], ans[B][B], cnt[N];
    
    inline void read(int &X) {
        X = 0;
        char ch = 0;
        int op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    inline void prework() {
        bnum = sqrt(n);
        for(int i = 1; i <= bnum; i++) {
            l[i] = (i - 1) * bnum + 1;
            r[i] = i * bnum;
        }
        if(r[bnum] < n) {
            bnum++;
            l[bnum] = r[bnum - 1] + 1;
            r[bnum] = n;
        }
    
        for(int i = 1; i <= bnum; i++)
            for(int j = l[i]; j <= r[i]; j++) {
                pos[j] = i;
                sum[i][a[j]]++;
            }
        for(int i = 1; i <= c; i++)
            for(int j = 1; j <= bnum; j++)
                sum[j][i] += sum[j - 1][i];
    
        for(int i = 1; i <= bnum; i++) {
            int res = 0;
            for(int j = l[i]; j <= n; j++) {
                cnt[a[j]]++;
                if(cnt[a[j]] > 0 && cnt[a[j]] % 2 == 0) res++;
                else if(cnt[a[j]] > 2) res--;
                ans[i][pos[j]] = res;
            }
            for(int j = l[i]; j <= n; j++)
                cnt[a[j]]--;
        }
    }
    
    inline void swap(int &x, int &y) {
        int t = x; 
        x = y;
        y = t;
    }
    
    int query(int x, int y) {
        int res = 0;
        if(pos[x] + 1 >= pos[y]) {
            for(int i = x; i <= y; i++) {
                cnt[a[i]]++;
                if(cnt[a[i]] > 0 && cnt[a[i]] % 2 == 0) res++;
                else if(cnt[a[i]] > 2) res--;
            }
            for(int i = x; i <= y; i++)
                cnt[a[i]]--;
        } else {
    /*        for(int i = x; i <= r[pos[x]]; i++)
                cnt[a[i]]++;
            for(int i = l[pos[y]]; i <= y; i++)
                cnt[a[i]]++; */
    
            res = ans[pos[x] + 1][pos[y] - 1];
            for(int i = x; i <= r[pos[x]]; i++) {
                cnt[a[i]]++;
                int tmp = sum[pos[y] - 1][a[i]] - sum[pos[x]][a[i]] + cnt[a[i]]; 
    /*            if(tmp > 0) {
                    if(tmp % 2 == 0) {
                        if(cnt[a[i]] % 2 != 0) res--;
                    } else {
                        if(cnt[a[i]] % 2 != 0) res++;
                        else res--;
                    }
                } else {
                    if(cnt[a[i]] > 0 && cnt[a[i]] % 2 == 0)
                        res++;
                } */
                
                if(tmp > 0 && tmp % 2 == 0) res++;
                else if(tmp > 2) res--;
            }
            for(int i = l[pos[y]]; i <= y; i++) {
                cnt[a[i]]++;
                int tmp = cnt[a[i]] + sum[pos[y] - 1][a[i]] - sum[pos[x]][a[i]]; 
    /*            if(tmp > 0) {
                    if(tmp % 2 == 0) {
                        if(cnt[a[i]] % 2 != 0) res--;
                    } else {
                        if(cnt[a[i]] % 2 != 0) res++;
                        else res--;
                    }
                } else {
                    if(cnt[a[i]] > 0 && cnt[a[i]] % 2 == 0)
                        res++;
                } */
    
                if(tmp > 0 && tmp % 2 == 0) res++;
                else if(tmp > 2) res--;
    
            }
    
            for(int i = x; i <= r[pos[x]]; i++)
                cnt[a[i]]--;
            for(int i = l[pos[y]]; i <= y; i++)
                cnt[a[i]]--;
        }
        return res;
    }
    
    int main() {
        read(n), read(c), read(m);
        for(int i = 1; i <= n; i++)
            read(a[i]);
        prework();
        
        for(int lastAns = 0, x, y; m--; ) {
            read(x), read(y);
            x = (x + lastAns) % n + 1, y = (y + lastAns) % n + 1;
            if(x > y) swap(x, y);
            printf("%d\n", lastAns = query(x, y));
        }
    
        return 0;
    }
  • 相关阅读:
    [ZJOI2010] 数字计数
    [USACO] 2004 Open MooFest 奶牛集会
    数星星
    [SCOI2011] 糖果
    西瓜种植
    [NOI2018] 归程
    [APIO2012] 派遣
    小K的农场
    妮可妮可妮 [Hash]
    [ZJOI2012] 灾难
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9466328.html
Copyright © 2020-2023  润新知