P3939 数颜色

Posted garen-wang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3939 数颜色相关的知识,希望对你有一定的参考价值。

数据结构学傻了吧!

这道题我一看上去:哦,数据结构。

再看上去:哦,分块题啊。

兴致冲冲地敲了个不熟练的分块,直接WA到只剩10pts。

过后很气地打了个暴力,60pts。。。

果然是暴力出奇迹啊!

不服气的我再打了个分块,终于写对了,却只有65pts,因为数据范围还是很大的,根号算法撑不住啦!

没错,就比暴力多5pts


正解是一个很玄的二分+vector。

对每一种颜色开一个vector,然后存入下标。

询问某种颜色的时候直接在这个vector里面upperbound和lowerbound两下就求出来了。

当然,这建立在首先sort过的情况。

不知道为什么,常数极小,一下就过了。。。


总结一下教训:

其实我在写那个分块的时候就已经跟暴力对拍过。并且数据生成器也一定不会出锅。

这个时候我的对拍一直停下来。

聪明人就应该知道我的分块已经写炸了,但我还以为我的generator搞错了。

最后还头铁地把分块交上去而不交一定对的暴力,最终GG。

故事告诉我们对拍的重要性和相信对拍的重要性!!!!

代码:

#include<cstdio>
#include<vector>
#include<algorithm>
const int maxn = 300005;

std::vector<int> vec[maxn];
int a[maxn];
int n, m;

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 * 10 + ch - ‘0‘, ch = getchar();
    return s * ans;
}
int main()
{
    n = read(), m = read();
    for(int i = 1; i <= n; i++)
    {
        a[i] = read();
        vec[a[i]].push_back(i);
    }
    for(int i = 1; i <= n; i++) std::sort(vec[i].begin(), vec[i].end());
    while(m--)
    {
        int opt = read();
        if(opt == 1)
        {
            int l = read(), r = read(), c = read();
            printf("%d
", std::upper_bound(vec[c].begin(), vec[c].end(), r) - std::lower_bound(vec[c].begin(), vec[c].end(), l));
        }
        else if(opt == 2)
        {
            int x = read();
            if(a[x] != a[x + 1])
            {
                (*std::lower_bound(vec[a[x]].begin(), vec[a[x]].end(), x))++;
                (*std::lower_bound(vec[a[x + 1]].begin(), vec[a[x + 1]].end(), x + 1))--;
                std::swap(a[x], a[x + 1]);
            }
        }
    }
    return 0;
}

以上是关于P3939 数颜色的主要内容,如果未能解决你的问题,请参考以下文章

题解 P3939 数颜色

P3939 数颜色

luogu P3939 数颜色

P3939 数颜色

P3939 数颜色 动态开点线段树

luogu P3939 数颜色 |vector