bzoj2120

带修改莫队

抄了个板子,跟莫队很像

莫队是两维排序,带修改的莫队是三维排序,(block[l],block[r],time) 我们把询问按照这个顺序排序,然后像普通莫队一样转移,唯一不同的是块要开到sqrt(n),还有转移区间之前要把对应区间的修改修改好,用一个cur指针指向当前修改,如果这个修改在当前莫队l,r之间,那么修改统计数组和答案,然后把位置对应的颜色改变,否则指把对应位置颜色改变。注意修改我们要维护一个之前的颜色,就是修改之前的颜色,因为莫队经过排序后,时间是无序的,所以我们要撤销之前的修改,那么我们必须维护一个last,之前的颜色,如果修改就改成修改后的v颜色,否则撤销修改,改成last颜色

#include<bits/stdc++.h>
using namespace std;
const int N = 10010;
int n, m, tot1, tot2, ans, size, l = 1, r, cur;
#define Id(x) (x - 1) / size + 1
struct data {
    int pos, col, last;
    data(int pos = 0, int col = 0, int last = 0) : pos(pos), col(col), last(last) {}
} c[N];
struct query {
    int l, r, id, tim;
    bool friend operator < (query A, query B)
    {
        if(Id(A.l) == Id(B.l))
        {
            if(Id(A.r) == Id(B.r)) return A.id < B.id;
            return Id(A.r) < Id(B.r);
        }
        return Id(A.l) < Id(B.l);
    }
} q[N];
int answer[N], a[N], cnt[1000010], t[1000010];
void add(int pos)
{
    ++cnt[pos];
    if(cnt[pos] == 1) ++ans;
}
void del(int pos)
{
    --cnt[pos];
    if(cnt[pos] == 0) --ans;
}
void change(int pos, int v) 
{
    if(pos >= l && pos <= r) 
    {
        add(v);
        del(a[pos]);
    }
    a[pos] = v;
}
void solve()
{
    sort(q + 1, q + tot2 + 1);
    for(int i = 1; i <= tot2; ++i)
    {
        while(cur < q[i].tim) {
            ++cur;
            change(c[cur].pos, c[cur].col);            
        }
        while(cur > q[i].tim) {
            change(c[cur].pos, c[cur].last);
            --cur;
        }
        while(l < q[i].l) {
            del(a[l]);
            ++l;
        }
        while(l > q[i].l) {
            --l;
            add(a[l]);
        }
        while(r < q[i].r) {
            ++r;
            add(a[r]);
        }
        while(r > q[i].r) {
            del(a[r]);
            --r;
        }
        answer[q[i].id] = ans; 
    }
    for(int i = 1; i <= tot2; ++i) printf("%d\n", answer[i]);
}
int main()
{
    scanf("%d%d", &n, &m);
    size = sqrt(n);
    for(int i = 1; i <= n; ++i) 
    {
        scanf("%d", &a[i]);
        t[i] = a[i];
    }
    for(int i = 1; i <= m; ++i)
    {
        char opt[10];
        int x, y;
        scanf("%s", opt);
        if(opt[0] == 'R')
        {
            scanf("%d%d", &x, &y);
            c[++tot1] = data(x, y, t[x]);
            t[x] = y;
        }
        if(opt[0] == 'Q')
        {
            ++tot2;
            scanf("%d%d", &q[tot2].l, &q[tot2].r);
            q[tot2].id = tot2;
            q[tot2].tim = tot1;
        }
    }
    solve();
    return 0;
}
View Code

 

posted @ 2017-08-06 15:25  19992147  阅读(85)  评论(0编辑  收藏  举报