【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且不超过1e6

题解:

树套树的大佬走开。。。

线段树套平衡树,树状数组套权值线段树?

或者分块?

当然没有问题。。。,但是如果没有修改,就是莫队水题

不过幸好是单点修改,我们可以对莫对进行改造,实现区间修改

再开一个时间戳,更新和L,R类似,单点删除,增加,交换

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define MAXN 1000005
#define ll long long
using namespace std;
ll n,m,blo_num,col[MAXN],block[MAXN],l=1,r=0,sum[MAXN],ans=0,t=0;
ll q_sum=0,c_sum=0,out[MAXN];
struct node1{
	ll l,r,id,t;
}ask[MAXN];
struct node2{
	ll pos,col;
}change[MAXN];
bool cmp(const node1 x,const node1 y){
	return x.l/blo_num==y.l/blo_num?(x.r/blo_num==y.r/blo_num?x.t<y.t:x.r<y.r):x.l<y.l;
}
void add(ll i){
	if(!sum[i]) ans++;
	sum[i]++;
}
void del(ll i){
	sum[i]--;
	if(!sum[i]) ans--;
}
int main(){
	scanf("%lld%lld",&n,&m);
	blo_num=(ll)pow(n,2.0/3.0);
	for(ll i=1;i<=n;i++){
		scanf("%lld",&col[i]);
		block[i]=i/blo_num;
	}
	for(ll i=1;i<=m;i++){
		char Q[5];
		scanf("%s",Q);
		if(Q[0]=='Q'){
			q_sum++;
			scanf("%lld%lld",&ask[q_sum].l,&ask[q_sum].r);
			ask[q_sum].id=q_sum;
			ask[q_sum].t=c_sum;
		}
		else{
			c_sum++;
			scanf("%lld%lld",&change[c_sum].pos,&change[c_sum].col);
		}
	}
	sort(ask+1,ask+q_sum+1,cmp);
	for(ll i=1;i<=q_sum;i++){
		while(l<ask[i].l) del(col[l++]);
		while(l>ask[i].l) add(col[--l]);
		while(r<ask[i].r) add(col[++r]);
		while(r>ask[i].r) del(col[r--]);
		while(t<ask[i].t){
			t++;
			if(ask[i].l<=change[t].pos&&change[t].pos<=ask[i].r){
				del(col[change[t].pos]);
        		add(change[t].col);
			}
            swap(col[change[t].pos],change[t].col);
		}
		while(t>ask[i].t){
			if(ask[i].l<=change[t].pos&&change[t].pos<=ask[i].r){
				del(col[change[t].pos]);
        		add(change[t].col);
			}
            swap(col[change[t].pos],change[t].col);
			t--;
		}
		out[ask[i].id]=ans;
	}
	for(ll i=1;i<=q_sum;i++)
		printf("%lld\n",out[i]);
	return 0;
}

 

posted @ 2019-08-19 20:32  xukl21  阅读(166)  评论(0编辑  收藏  举报