BZOJ-2120 数颜色
数颜色
带修莫队 模板题
看到别人题解,发现有个小技巧,时间纬度在更改的时候直接 swap 当前值和要修改的值,下次回来的时候 swap 回去是一样的,这样就可以不用多记录状态了
https://fangkaipeng.com/?p=1504
我还发现非常 BZOJ 的数据和 AcWing 的数据相当奇怪,用分块大小为 \(\sqrt{n}\) 作为分块会更加快,而洛谷的数据用分块大小为 \(n^{\frac{2}{3}}\) 会更快
我的猜测是数据范围约束的问题,BZOJ 和 AcWing 的条件约束说修改的次数在于 1000 次以下,可能就导致了时间纬度修改的比较少,因此最优分块趋近于 \(\sqrt{n}\)
https://www.acwing.com/problem/content/2523/
正常的复杂度分析来说,分块大小应该为 \(n^{\frac{2}{3}}\),复杂度为 \(O(n^{\frac{5}{3}})\)
https://www.luogu.com.cn/problem/P1903
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define endl '\n'
#define pii pair<int, int>
const int maxn = 133333 + 10;
const ll maxm = 1e6 + 10;
const ll inf = 1e17 + 10;
int num[maxn], pos[maxm], cnt[maxm];
int l = 1, r = 0, ans = 0, t = 0, nn = 0;
int last[maxn];
struct node
{
int l, r, t, id;
node(){}
node(int _l, int _r, int _t, int _id){l = _l; r = _r; t = _t; id = _id;}
}seg[maxn], change[maxn];
bool cmp(const node& a, const node& b)
{
return pos[a.l] ^ pos[b.l] ? pos[a.l] < pos[b.l] : (pos[a.r] ^ pos[b.r] ? pos[a.r] < pos[b.r] : a.t < b.t);
}
inline void add(int x)
{
ans += (++cnt[num[x]] == 1);
}
inline void del(int x)
{
ans -= (--cnt[num[x]] == 0);
}
inline void update(int x)
{
if(change[x].t >= l && change[x].t <= r)
{
del(change[x].t);
swap(num[change[x].t], change[x].l);
add(change[x].t);
}
else swap(num[change[x].t], change[x].l);
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
// freopen("text.in", "rb", stdin);
// freopen("text.out", "wb", stdout);
int n, m;
scanf("%d%d", &n, &m);
int maxx = 0;
for(int i=1; i<=n; i++) {cin >> num[i]; maxx = num[i] > maxx ? num[i] : maxx;}
nn = pow(maxn, 2.0 / 3.0);
for(int i=1; i<=maxx; i++) pos[i] = i / nn;
int tq = 0, tr = 0;
for(int i=0; i<m; i++)
{
char a;
int x, y;
scanf(" %c%d%d", &a, &x, &y);
if(a == 'Q')
{
seg[tq] = node(x, y, tr, tq);
tq++;
}
else
{
change[tr] = node(y, 0, x, 0);
tr++;
}
}
sort(seg, seg + tq, cmp);
t = 0;
for(int i=0; i<tq; i++)
{
while(t < seg[i].t) update(t++);
while(t > seg[i].t) update(--t);
while(r < seg[i].r) add(++r);
while(l > seg[i].l) add(--l);
while(r > seg[i].r) del(r--);
while(l < seg[i].l) del(l++);
last[seg[i].id] = ans;
}
for(int i=0; i<tq; i++)
printf("%d\n", last[i]);
return 0;
}