題名
ポータルP1903【全国研修チーム】色数/メンテナンスキュー
回答
通常のMoチームと比較して、変更操作に対応する時間軸がもう1つあります。各クエリは、2次元(l、r)(l、r)で構成されます。(l 、r )は3次元になります(l、r、t)(l、r、t)(l 、r 、t )。基本的な考え方は、最初のw − 1w-1をクエリすることです。w−1次元ブロックであるため、前面w − 1 w-1w−ブロック内の1次元の値の範囲が制限されているため、wwthwディメンションはブロック内で順序付けられており、この時点で各クエリをより短いルートでトラバースできます。
具体的には、クエリ間隔[1、N] [1、N][ 1 、N ]は、l、r、tl、r、tのブロックに分割されますl 、r 、tは、1番目、2番目、および3番目のキーワードの順序です。クエリ数を設定するQQQ.変更TTTとNNNは同じ大きさです。[1、N] [1、N]とします。[ 1 、N ]はaaに分けられますその後、ブロック、LLlはブロックにaaがありますa 种, r r rはブロックにaaを持っていますaと入力すると、ブロックの総数は2 a ^ 2になります。a2。同じブロックで、tttが単調である場合、各ブロック境界で時間軸が変更される回数はO(N)O(N)です。O (N )、各ブロック内の変更回数はO(N)O(N)O (N )、変更の総数はO(a 2 N)O(a ^ 2N)O (a2 N);l、rl、rl 、ブロック内のrの最大値と最小値の差はO(N / a)O(N / a)です。O (N / a )、ブロック間で変更O(N)O(N)O (N )、変更の総数O(N×N / a + a 2 N)O(N \ times N / a + a ^ 2N)O (N××N / a+a2 N)。式N2 / a = a 2 NN ^ 2 / a = a ^ 2NによってN2 /a=a2 N、ブロック数はN 1/3 N ^ {1/3}N1 / 3、ブロックサイズN 2/3 N ^ {2/3N2 / 3。
最適化にはパリティソートを使用できます。基本的な原理は、ブロックの最後の次元、つまりw − 1w-1を除算することです。w−1次元の奇数ブロックからwww次元の昇順ソート、偶数ブロックwww次元の降順でソートし、ww隣接するブロック間のw次元の変更回数は減少する可能性があります。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 133335, maxc = 1000005;
int N, M, qn, rn, res, id[maxn], col[maxn], rec[maxn], cnt[maxc];
struct P1
{
int l, r, t, k;
bool operator<(const P1 &b) const
{
if (id[l] != id[b.l])
return l < b.l;
if (id[r] != id[b.r])
return r < b.r;
return (id[r] & 1) ? t < b.t : t > b.t;
}
} Q[maxn];
struct P2
{
int k, c;
} R[maxn];
inline int read()
{
int x = 0;
char c = 0;
for (; c < '0' || c > '9'; c = getchar())
;
for (; c >= '0' && c <= '9'; c = getchar())
x = (x << 1) + (x << 3) + c - '0';
return x;
}
inline void add(int i)
{
if (!cnt[col[i]]++)
++res;
}
inline void del(int i)
{
if (!--cnt[col[i]])
--res;
}
inline void upd(int t, int i)
{
int p = R[t].k;
if (Q[i].l <= p && p <= Q[i].r)
del(p), swap(col[p], R[t].c), add(p);
else
swap(col[p], R[t].c);
}
int main()
{
N = read(), M = read();
for (int i = 1; i <= N; ++i)
col[i] = read();
for (int i = 1; i <= M; ++i)
{
char op;
scanf(" %c", &op);
if (op == 'Q')
Q[++qn] = P1{
read(), read(), rn, qn};
else
R[++rn] = P2{
read(), read()};
}
int w = pow(N, 2.0 / 3.0), t = ceil((double)N / w);
for (int i = 1; i <= t; ++i)
for (int l = (i - 1) * w + 1, r = min(i * w, N), j = l; j <= r; ++j)
id[j] = i;
sort(Q + 1, Q + qn + 1);
for (int i = 1, l = Q[1].l, r = l - 1, t = 0, ql, qr, qt; i <= qn; ++i)
{
ql = Q[i].l, qr = Q[i].r, qt = Q[i].t;
while (l < ql)
del(l++);
while (l > ql)
add(--l);
while (r < qr)
add(++r);
while (r > qr)
del(r--);
while (t < qt)
upd(++t, i);
while (t > qt)
upd(t--, i);
rec[Q[i].k] = res;
}
for (int i = 1; i <= qn; ++i)
printf("%d\n", rec[i]);
return 0;
}