题解:
将数列分块一下,
变成sqrt ( n ) 块,每一块维护一个双端队列,以及建一个桶记录这一块中不同的数的个数。
对于操作①,我们暴力操作左右两边的块,
对于中间的块就是双端队列左边删一个,右边加一个,注意维护桶
对于操作②,暴力枚举左右两边的块,通过桶查询中间的块即可
时间复杂度:O ( n*sqrt ( n ) )
没怎么用过双端队列,所以维护的有点粗暴
代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#define N 100005
using namespace std;
int A[335][N], Belong[N], C[355], D[355], num, cnt, n, m;
void read(int &x)
{
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s >= '0' && s <= '9') { x = x * 10 + (s - '0'); s = getchar(); }
x = x * f;
}
deque <int> Q[N];
int main()
{
freopen("queue.in", "r", stdin);
freopen("queue.out", "w", stdout);
read(n); read(m);
num = sqrt(n);
for (int i = 1; i <= n; i++)
{
int x; read(x);
if (i > num * cnt) ++cnt;
Q[cnt].push_back(x);
Belong[i] = cnt, ++A[cnt][x];
}
while (m--)
{
int opt; read(opt);
if (opt == 1)
{
int l, r; read(l); read(r);
if (Belong[l] == Belong[r])
{
int G = Belong[l];
l = l % num; if (l == 0) l = num;
r = r % num; if (r == 0) r = num;
for (int i = 1; i < l; i++)
C[i] = Q[G].front(), Q[G].pop_front();
for (int i = 1; i <= num - r; i++)
D[i] = Q[G].back(), Q[G].pop_back();
int x = Q[G].back(); Q[G].pop_back(); Q[G].push_front(x);
for (int i = l - 1; i >= 1; i--) Q[G].push_front(C[i]);
for (int i = 1; i <= num - r; i++) Q[G].push_back(D[(num - r) - i + 1]);
}
else
{
int G = Belong[l], k = l; while (Belong[k + 1] == G) ++k;
int len1 = k - l + 1;
for (int i = 1; i <= len1; i++)
C[len1 - i + 1] = Q[G].back(), Q[G].pop_back(), A[G][C[len1 - i + 1]]--;
int F = Belong[r], h = r; while (Belong[h - 1] == F) --h;
int len2 = r - h + 1;
for (int i = 1; i <= len2; i++)
D[i] = Q[F].front(), Q[F].pop_front(), A[F][D[i]]--;
Q[G].push_back(D[len2]), A[G][D[len2]]++;
for (int i = 1; i < len1; i++) Q[G].push_back(C[i]), A[G][C[i]]++;
for (int i = len2 - 1; i >= 1; i--) Q[F].push_front(D[i]), A[F][D[i]]++;
int x = Q[F - 1].back(); if (F == G + 1) x = C[len1];
Q[F].push_front(x), A[F][x]++;
int last = C[len1];
for (int i = G + 1; i <= F - 1; i++)
{
Q[i].push_front(last); A[i][last]++;
last = Q[i].back(); Q[i].pop_back();
A[i][last]--;
}
}
}
else
{
int l, r, K, orz = 0; read(l); read(r); read(K);
if (Belong[l] == Belong[r])
{
int G = Belong[l];
l = l % num; if (l == 0) l = num;
r = r % num; if (r == 0) r = num;
for (int i = 1; i < l; i++)
C[i] = Q[G].front(), Q[G].pop_front();
for (int i = 1; i <= num - r; i++)
D[i] = Q[G].back(), Q[G].pop_back();
for (int i = l - 1; i >= 1; i--)
{
if (C[i] == K) ++orz;
Q[G].push_front(C[i]);
}
for (int i = 1; i <= num - r; i++)
{
if (D[(num - r) - i + 1] == K) ++orz;
Q[G].push_back(D[(num - r) - i + 1]);
}
orz = A[G][K] - orz;
}
else
{
int G = Belong[l], k = l; while (Belong[k + 1] == G) ++k;
int len1 = k - l + 1;
for (int i = 1; i <= len1; i++) C[len1 - i + 1] = Q[G].back(), Q[G].pop_back();
for (int i = 1; i <= len1; i++)
{
if (C[i] == K) ++orz;
Q[G].push_back(C[i]);
}
int F = Belong[r], h = r; while (Belong[h - 1] == F) --h;
int len2 = r - h + 1;
for (int i = 1; i <= len2; i++) D[i] = Q[F].front(), Q[F].pop_front();
for (int i = len2; i >= 1; i--)
{
if (D[i] == K) ++orz;
Q[F].push_front(D[i]);
}
for (int i = G + 1; i <= F - 1; i++) orz += A[i][K];
}
printf("%d\n", orz);
}
}
return 0;
}