JZOJ5924. 【NOIP2018模擬10.23】Queue
阿新 • • 發佈:2018-11-05
題意:
資料範圍:
Analysis:
如果用二維資料結構強行去維護它,會很難做,不妨考慮分塊。
發現每一次就是對於每一個塊之間最後一個挪到第一個,最後一個和第一個單獨考慮。
那麼要維護相對位置,和
的個數,後面那個可以開個桶來做,前面的顯然用連結串列來維護,這樣就做完了。
複雜度:
記錄另一個做法:考慮每一次挪位操作,我們當做往他們之前插入一個虛點,原來的點當做不存在但是不刪除。然後把操作離線下來,用
把最終序列按照如上維護出來,並且記錄下來每一次加點,刪點(不存在的相當於賦為0)的資訊。
我們現在區間固定了下來,那麼問題轉化為,每一次對於一個點權資訊更改,詢問某個區間數值等於
的個數。複雜度:
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;
}