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
Source
解题思路: 与普通莫队的差别是,带有修改操作,所以当前排序的优先级是
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