BZOJ 2120 数颜色 (带修改莫队)

2120: 数颜色

Time Limit: 6 Sec  Memory Limit: 259 MB
Submit: 9394  Solved: 3866
[Submit][Status][Discuss]

Description

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?

Input

第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

Output

对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。

Sample Input

6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6

Sample Output

4
4
3
4

HINT

对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。

2016.3.2新加数据两组by Nano_Ape

扫描二维码关注公众号,回复: 3315988 查看本文章

Source

[Submit][Status][Discuss]

解题思路: 与普通莫队的差别是,带有修改操作,所以当前排序的优先级是

1。查询左端点所在的块

2.查询右端点所在的块

3.该查询之前进行修改的次数

用一个now标记当前修改了多少次,如果now大于当前查询点修改的次数就修改回去,否则继续往后修改。

分成的块大概是N的pow(n,2/3)次方,时间复杂度大概是pow(n,5/3);

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#define LL long long
using namespace std;
#define N 2000006

int qnum,cnum;
int len,now,ans;
int block[N];
struct node
{
    int l,r,id,pre;
    friend bool operator <(node x,node y)
    {
        if(block[x.l]!=block[y.l])return block[x.l]<block[y.l];
        if(block[x.r]!=block[y.r])return block[x.r]<block[y.r];
        return x.pre<y.pre;
    }
}Q[N];

struct node1
{
    int pos,val;
}C[N];

int a[N];
int vis[N];

void add(int x)
{
    if(++vis[a[x]]==1)ans++;
}

void sub(int x)
{
    if(--vis[a[x]]==0)ans--;
}


void work(int now,int i)
{
    if(C[now].pos>=Q[i].l && C[now].pos<=Q[i].r)
    {
        if(--vis[a[C[now].pos]]==0)ans--;
        if(++vis[C[now].val]==1)ans++;
    }
    swap(a[C[now].pos],C[now].val);
}

int sum[N];
void solve()
{
    int l=1,r=0;
    now=0;
    for(int i=1;i<=qnum;i++)
    {
        while(r<Q[i].r) add(++r);
        while(r>Q[i].r) sub(r--);
        while(l<Q[i].l) sub(l++);
        while(l>Q[i].l) add(--l);

        while(now<Q[i].pre) work(++now,i);
        while(now>Q[i].pre) work(now--,i);
        sum[Q[i].id]=ans;
    }
    for(int i=1;i<=qnum;i++)
    {
        printf("%d\n",sum[i]);
    }
}


int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    len=pow(n,0.7777777);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    char s[8];
    int l,r;
    for(int i=1;i<=m;i++)
    {
        scanf("%s%d%d",s,&l,&r);
        if(s[0]=='Q')
        {
            ++qnum;
            Q[qnum].l=l,Q[qnum].r=r;
            Q[qnum].id=qnum,Q[qnum].pre=cnum;
        }
        else if(s[0]=='R')
        {
            ++cnum;
            C[cnum].pos=l,C[cnum].val=r;
        }
    }
    for(int i=1;i<=n;i++)block[i]=i/len+1;
    sort(Q+1,Q+1+qnum);
    solve();
    return 0;
}

学习博客:https://www.cnblogs.com/zwfymqz/p/7154145.html

猜你喜欢

转载自blog.csdn.net/weixin_40894017/article/details/82690979