[CF455D] Serega and Fun

[CF455D] Serega and Fun - 分块

Description

给定长度为N(N<=100000)的序列,支持两种操作:1 l r 将区间l到r依次向右移动一位,a[r]移动到 [l],2 l r k 询问区间l到r中k出现次数。

Solution

考虑分块,每个块内用 deque 维护(这个东西好处就在于不仅支持双端操作还可以下标索引),同时维护一个块内每个值的出现次数

然后对于操作就暴力处理一下

#include <bits/stdc++.h>
using namespace std;

#define int long long

const int B = 360;
const int N = 100005;

int block(int x)
{
    return x / B;
}

int offset(int x)
{
    return x % B;
}

deque<int> a[B];
signed c[B][N];

int n, q;

signed main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        int x;
        cin >> x;
        a[block(i)].push_back(x);
        c[block(i)][x]++;
    }
    cin >> q;
    int lastans = 0;
    for (int i = 0; i < q; i++)
    {
        int op, l, r, k;
        cin >> op >> l >> r;
        l = (l + lastans - 1) % n;
        r = (r + lastans - 1) % n;

        if (l > r)
            swap(l, r);
        if (op == 2)
            cin >> k;
        k = (k + lastans - 1) % n + 1;

        int L = block(l);
        int R = block(r);
        l = offset(l);
        r = offset(r);

        if (op == 1)
        {
            if (L == R)
            {
                int x = a[R][r];
                a[R].erase(a[R].begin() + r);
                a[L].insert(a[L].begin() + l, x);
            }
            else
            {
                for (int i = L; i < R; i++)
                {
                    int x = a[i].back();
                    a[i].pop_back();
                    c[i][x]--;
                    c[i + 1][x]++;
                    a[i + 1].push_front(x);
                }
                int x = a[R][r + 1];
                a[R].erase(a[R].begin() + r + 1);
                a[L].insert(a[L].begin() + l, x);
                c[R][x]--;
                c[L][x]++;
            }
        }
        else
        {
            int ans = 0;
            if (L == R)
            {
                for (int i = l; i <= r; i++)
                    ans += a[L][i] == k;
            }
            else
            {
                for (int i = l; i < a[L].size(); i++)
                    ans += a[L][i] == k;
                for (int i = 0; i <= r; i++)
                    ans += a[R][i] == k;
                for (int i = L + 1; i <= R - 1; i++)
                    ans += c[i][k];
            }
            cout << (lastans = ans) << endl;
        }
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14659160.html