毒瘤数据卡普通莫队!!
这道题跟普通的莫队题目差不多,但是多了一个修改操作。
所以带修莫队就横空出世了。
普通莫队记录左端点和右端点,那么这里就再记录一个时间轴,表示当时已经执行过几次修改。
之后莫队模板就有六个while,前四个是一样的。
最后两个判断当前修改次数和目标修改次数的关系。这个就是灵魂了。
重点看这个时间轴上的修改吧。
void change(int idx, int i)
{
if(q[i].l <= c[idx].p && c[idx].p <= q[i].r)// 当修改点在询问区间内才需要维护答案
{
del(a[c[idx].p]);
add(c[idx].col);
}
std::swap(a[c[idx].p], c[idx].col);// 很巧妙的一个操作,这样操作答案不变,程序更简洁
}
完整代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
const int maxn = 50005;
struct Query
{
int l, r, id, pre;
} q[maxn];
int q_tot;
struct Change
{
int p, col;
} c[maxn];
int c_tot;
int belong[maxn], block;
int a[maxn];
int out[maxn];
int n, m;
int l, r, res, changed;
int cnt[1000005];
bool cmp(Query x, Query y)// 按照左右端点所在块排序,再按时间排序
{
if(belong[x.l] != belong[y.l]) return belong[x.l] < belong[y.l];
if(belong[x.r] != belong[y.r]) return belong[x.r] < belong[y.r];
return x.pre < y.pre;
}
int read()
{
int ans = 0, s = 1;
char ch = getchar();
while(ch > '9' || ch < '0'){ if(ch == '-') s = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') ans = (ans << 3) + (ans << 1) + ch - '0', ch = getchar();
return s * ans;
}
void add(int x)
{
if(++cnt[x] == 1) res++;
}
void del(int x)
{
if(--cnt[x] == 0) res--;
}
void change(int idx, int i)
{
if(q[i].l <= c[idx].p && c[idx].p <= q[i].r)
{
del(a[c[idx].p]);
add(c[idx].col);
}
std::swap(a[c[idx].p], c[idx].col);
}
void moqueue()
{
block = pow(n, 0.6666667);// 块大小要换成这样
for(int i = 1; i <= n; i++) belong[i] = (i - 1) / block + 1;
std::sort(q + 1, q + q_tot + 1, cmp);
l = 1, r = 0, res = 0, changed = 0;
for(int i = 1; i <= q_tot; i++)
{
while(r < q[i].r) add(a[++r]);
while(r > q[i].r) del(a[r--]);
while(l > q[i].l) add(a[--l]);
while(l < q[i].l) del(a[l++]);
while(changed < q[i].pre) change(++changed, i);// 改少了
while(changed > q[i].pre) change(changed--, i);// 改多了
out[q[i].id] = res;
}
}
int main()
{
n = read(), m = read();
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 1; i <= m; i++)
{
char opt[3]; scanf("%s", opt);
if(opt[0] == 'Q')
{
int x = read(), y = read();
q[++q_tot] = (Query){x, y, q_tot, c_tot};
}
else if(opt[0] == 'R')
{
int p = read(), col = read();
c[++c_tot] = (Change){p, col};
}
}
moqueue();
for(int i = 1; i <= q_tot; i++) printf("%d\n", out[i]);
return 0;
}