题意:
数据范围:
Analysis:
如果用二维数据结构强行去维护它,会很难做,不妨考虑分块。
发现每一次就是对于每一个块之间最后一个挪到第一个,最后一个和第一个单独考虑。
那么要维护相对位置,和
a
i
=
k
a_i=k
ai=k的个数,后面那个可以开个桶来做,前面的显然用链表来维护,这样就做完了。
复杂度:
O
(
n
n
)
O(n\sqrt{n})
O(nn)
记录另一个做法:考虑每一次挪位操作,我们当做往他们之前插入一个虚点,原来的点当做不存在但是不删除。然后把操作离线下来,用
s
p
l
a
y
splay
splay把最终序列按照如上维护出来,并且记录下来每一次加点,删点(不存在的相当于赋为0)的信息。
我们现在区间固定了下来,那么问题转化为,每一次对于一个点权信息更改,询问某个区间数值等于
k
k
k的个数。复杂度:
O
(
(
m
+
n
)
log
n
)
O((m+n)\log n)
O((m+n)logn)
Code:
# include<cstdio>
# include<cstring>
# include<algorithm>
# include<cmath>
# pragma GCC optimize(2)
using namespace std;
const int N = 1e5 + 5;
const int K = 8e2 + 5;
int L[K],R[K],h[K],t[K],pos[N];
int num[K][N],nx[N],las[N],a[N];
int n,m,tot,len;
inline int read()
{
int x = 0; char ch = getchar();
for (; ch < '0' || ch > '9' ; ch = getchar());
for (; ch >= '0' && ch <= '9' ; ch = getchar()) x = x * 10 + ch - '0';
return x;
}
inline void add(int p,int x,int v) { num[p][x] += v; }
int main()
{
freopen("queue.in","r",stdin);
freopen("queue.out","w",stdout);
n = read(),m = read(); if (n) len = sqrt(n * 5),tot = n / len + (n % len ? 1 : 0);
for (int i = 1 ; i <= n ; ++i) a[i] = read();
for (int i = 1 ; i <= tot ; ++i) L[i] = R[i - 1] + 1,R[i] = min(n,len * i);
for (int i = 1 ; i <= tot ; ++i)
{
h[i] = L[i],t[i] = R[i]; add(i,a[L[i]],1),pos[L[i]] = i;
for (int j = L[i] + 1 ; j <= R[i] ; ++j) las[j] = j - 1,nx[j - 1] = j,add(i,a[j],1),pos[j] = i;
}
while (m--)
{
int opt = read(),l = read(),r = read();
if (opt == 1)
{
if (l == r) continue;
if (pos[l] == pos[r])
{
int k = l - L[pos[l]],p = h[pos[l]],k1 = R[pos[l]] - r,p1 = t[pos[l]];
while (k--) p = nx[p]; while (k1--) p1 = las[p1];
if (p == h[pos[l]]) h[pos[l]] = p1;
if (p1 == t[pos[l]]) t[pos[l]] = las[p1];
las[nx[p1]] = las[p1],nx[las[p1]] = nx[p1];
las[p1] = las[p],nx[las[p]] = p1,nx[p1] = p,las[p] = p1;
}else
{
int now = t[pos[l]],k1 = R[pos[l]] - l,p1 = t[pos[l]];
while (k1--) p1 = las[p1]; int z = las[p1],y = nx[p1]; t[pos[l]] = las[now],nx[las[now]] = 0;
add(pos[l],a[now],-1);
for (int i = pos[l] + 1 ; i < pos[r] ; ++i)
{
add(i,a[now],1),las[now] = 0;
las[h[i]] = now,nx[now] = h[i],h[i] = now;
now = t[i],nx[las[now]] = 0,t[i] = las[now]; add(i,a[now],-1);
} las[now] = 0;
int k = r - L[pos[r]],p = h[pos[r]];
while (k--) p = nx[p];
if (p == t[pos[r]]) t[pos[r]] = las[p] ? las[p] : now;
if (p != h[pos[r]]) las[h[pos[r]]] = now,nx[now] = h[pos[r]];
else nx[now] = nx[p],las[nx[p]] = now;
if (p != h[pos[r]]) nx[las[p]] = nx[p],las[nx[p]] = las[p];
h[pos[r]] = now,add(pos[r],a[now],1),add(pos[r],a[p],-1);
nx[p] = p1,las[p1] = p,las[p] = z,nx[z] = p,add(pos[l],a[p],1);
if (!y) t[pos[l]] = p,nx[p] = las[p1] = 0; if (!z) h[pos[l]] = p;
}
}else
{
int k = read(),ans = 0;
if (pos[l] == pos[r])
{
int cnt = l - L[pos[l]],p = h[pos[l]];
while (cnt--) p = nx[p]; cnt = r - l + 1;
while (cnt--) ans += a[p] == k,p = nx[p];
}else
{
int cnt = R[pos[l]] - l + 1,p = t[pos[l]];
while (cnt--) ans += a[p] == k,p = las[p];
cnt = r - L[pos[r]] + 1,p = h[pos[r]];
while (cnt--) ans += a[p] == k,p = nx[p];
for (int i = pos[l] + 1 ; i < pos[r] ; ++i) ans += num[i][k];
}
printf("%d\n",ans);
}
}
return 0;
}