【bzoj2120】数颜色

*题目描述:
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?
*输入:
第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。
*输出:
对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。
*样例输入:
6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
*样例输出:
4
4
3
4
*提示:
对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。
*题解:
分块。用一个链表把同一颜色的位置都串起来,然后每次修改就在链表里面暴力删暴力插,查询的话就是预处理是先对链表的前一个出现的颜色的位置排序,只要块内元素的前一个出现的颜色的坐标在询问的区间之外的话(

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

#ifdef WIN32
    #define LL "%I64d"
#else
    #define LL "%lld"
#endif

#ifdef CT
    #define debug(...) printf(__VA_ARGS__)
    #define setfile() 
#else
    #define debug(...)
    #define filename ""
    #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout);
#endif

#define R register
#define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
#define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
char B[1 << 15], *S = B, *T = B;
inline int FastIn()
{
    R char ch; R int cnt = 0; R bool minus = 0;
    while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
    ch == '-' ? minus = 1 : cnt = ch - '0';
    while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
    return minus ? -cnt : cnt;
}
#define maxn 10010
#define maxc 1000010
int a[maxn], block, n, ans, last[maxc], prev[maxn], next[maxn], b[maxn], ql, qr, id[maxn];
inline void reset(R int x)
{
    R int l = x * block, r = (x + 1) * block - 1; cmin(r, n);
    for (R int i = l; i <= r; ++i)
        b[i] = prev[i];
    std::sort(b + l, b + r + 1);
}
inline void build(R int x)
{
    R int l = x * block, r = (x + 1) * block - 1; cmin(r, n);
    for (R int i = l; i <= r; ++i)
    {
        R int col = a[i];
        next[last[col]] = i;
        b[i] = prev[i] = last[col];
        last[col] = i;
    }
    std::sort(b + l, b + r + 1);
}
inline void voi_query(R int l, R int r)
{
    for (R int i = l; i <= r; ++i) if (prev[i] < ql) ++ans;
}
inline void query(R int x)
{
    R int l = x * block, r = (x + 1) * block - 1;
    ans += std::upper_bound(b + l, b + r + 1, ql - 1) - b - l;
}
int main()
{
//  setfile();
    n = FastIn(); R int m = FastIn();
    block = sqrt(n);
    for (R int i = 1; i <= n; ++i) a[i] = FastIn(), id[i] = i / block;
    for (R int i = 0; i <= n / block; ++i) build(i);
    for (; m; --m)
    {
        R char opt;
        while (opt = getc(), opt < 'A' || opt > 'Z');
        if (opt == 'Q')
        {
            ans = 0;
            ql = FastIn(), qr = FastIn();
            if (id[ql] == id[qr])
                voi_query(ql, qr);
            else
            {
                voi_query(ql, (id[ql] + 1) * block - 1);
                voi_query(id[qr] * block, qr);
                for (R int i = id[ql] + 1; i < id[qr]; ++i) query(i);
            }
            printf("%d\n", ans );
        }
        else
        {
            R int x = FastIn(), c = FastIn();
            if (last[a[x]] == x) last[a[x]] = prev[x]; 
            next[prev[x]] = next[x];
            prev[next[x]] = prev[x];
            reset(id[next[x]]);
            if (last[c] > x && last[c])
            {
                for (R int i = last[c]; i; i = prev[i])
                    if (prev[i] < x)
                    {
                        next[x] = i;
                        prev[x] = prev[i];
                        next[prev[i]] = x;
                        prev[i] = x;
                        reset(id[i]);
                        break;
                    }
            }
            else
            {
                if (x > last[c])
                {
                    prev[x] = last[c];
                    next[last[c]] = x;
                    last[c] = x;
                }
                else last[c] = x, next[x] = prev[x] = 0;
            }
            reset(id[x]);
            a[x] = c;
        }
    }
    return 0;
}
/*
2 3
1 2
Q 1 2
R 1 2
Q 1 2
*/
posted @ 2016-05-22 21:46  cot  阅读(235)  评论(7编辑  收藏  举报