zoukankan      html  css  js  c++  java
  • 【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
    ", 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
    */
  • 相关阅读:
    各种筛法与莫比乌斯反演
    欧拉函数技巧与学习笔记
    莫比乌斯函数与欧拉函数的单个值的快速求法
    最短路算法总结
    NOI2018网络同步赛游记
    中国剩余定理及其扩展学习笔记
    构造方法的格式
    private关键字
    成员变量和局部变量的区别
    数据加密代码实现
  • 原文地址:https://www.cnblogs.com/cocottt/p/5550952.html
Copyright © 2011-2022 走看看