数颜色

数颜色( 二分\(\star\star \))

  • 时限:\(1s\) 内存:\(256M\)

Descrption

  • \(C\) 的兔子不是雪白的,而是五彩缤纷的。每只兔子都有一种颜色,不同的兔子可能有相同的颜色。小 \(C\) 把她标号从 \(1\)\(n\)\(n\)只兔子排成长长的一排,来给他们喂胡萝卜吃。排列完成后,第\(i\)只兔子的颜色是\(a_i\)

  • 俗话说得好,"萝卜青菜,各有所爱"。小 \(C\) 发现,不同颜色的兔子可能有对胡萝卜的不同偏好。比如,银色的兔子最喜欢吃金色的胡萝卜,金色的兔子更喜欢吃胡萝卜叶子,而绿色的兔子却喜欢吃酸一点的胡萝卜……为了满足兔子们的要求,小 \(C\) 十分苦恼。所以,为了使得胡萝卜喂得更加准确,小 \(C\) 想知道在区间\([l_j,r_j]\)里有多少只颜色为\(c_j\)的兔子。

  • 不过,因为小 \(C\) 的兔子们都十分地活跃,它们不是很愿意待在一个固定的位置;与此同时,小 \(C\) 也在根据她知道的信息来给兔子们调整位置。所以,有时编号为\(x_j\)\(x_{j+1}\)的两只兔子会交换位置。

  • \(C\) 被这一系列麻烦事给难住了。你能帮帮她吗?

Input

  • 输入第 \(1\) 行两个正整数\(n,m\)

  • 输入第 \(2\)\(n\)个正整数,第\(i\)个数表示第\(i\)只兔子的颜色\(a_i\)

  • 输入接下来\(m\)行,每行为以下两种中的一种:

    • \(1\ l_j\ r_j\ c_j\) :询问在区间\([l_j,r_j]\)里有多少只颜色为\(c_j\)的兔子;
    • \(2\ x_j\)\(x_j\)\(x_{j+1}\)两只兔子交换了位置

Output

  • 对于每个 \(1\) 操作,输出一行一个正整数,表示你对于这个询问的答案

Sample Input

6 5
1 2 3 2 3 3
1 1 3 2
1 4 6 3
2 3
1 1 3 2
1 4 6 3

Sample Output

1
2
2
3

Hint

  • 样例说明

    • 前两个 \(1\) 操作和后两个 \(1\) 操作对应相同;在第三次的 \(2\) 操作后,\(3\) 号兔子和 \(4\) 号兔子交换了位置,序列变为 \(1\ 2\ 2\ 3\ 3\ 3\)
  • 子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试只解决一部分测试数据。

    • 对于所有测试点,有$1\leq l_j \leq r_j \leq n , 1 \leq x_j \leq n $

    • 每个测试点的数据规模及特点如下表:

  • 特殊性质 1:保证对于所有操作 1,有\(|r_j - l_j| \leq 20\) 或 \(|r_j - l_j| \geq n-20\)

  • 特殊性质 2:保证不会有两只兔子相同颜色的兔子。

  • 来源:\(luogup3939\)

分析

  • 我们可以用类似的桶记录下某一个颜色出现的位置,然后查询 \([l,r]\) 颜色 \(x\) 出现几次,我们可以二分找到 \(l\) 在桶中的位置,\(r\) 在桶中的位置,则个数即为两个位置之差。
  • 交换也相对比较简单,当 \(a[i]==a[i+1]\) 时不用交换,当不等时,在各自的桶值把位置修改下,然后再把两个 \(a[i],a[i+1]\) 交换下即可。

Code

#include <bits/stdc++.h>
const int maxn=3e5+5;
std::vector<int> q[maxn];
int n,m,a[maxn];
void Init(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		q[a[i]].push_back(i);
	}
}
void Solve(){
	int l,r,opt,x;
	while(m--){
		scanf("%d",&opt);
		int pos_l,pos_r;
		if(opt==1){
			scanf("%d%d%d",&l,&r,&x);
			pos_l=std::lower_bound(q[x].begin(),q[x].end(),l)-q[x].begin();
			pos_r=std::upper_bound(q[x].begin(),q[x].end(),r)-q[x].begin()-1;
			if(pos_r<pos_l)//区间没有x时,pos_r比pos_l少1
				printf("0\n");
			else
				printf("%d\n",pos_r-pos_l+1);
		}
		else{
			scanf("%d",&x);
			if(a[x]==a[x+1])continue;
			pos_l=std::lower_bound(q[a[x]].begin(),q[a[x]].end(),x)-q[a[x]].begin();
			q[a[x]][pos_l]++;
			pos_r=std::lower_bound(q[a[x+1]].begin(),q[a[x+1]].end(),x+1)-q[a[x+1]].begin();
			q[a[x+1]][pos_r]--;
			std::swap(a[x],a[x+1]);
		}
	}
}
int main(){
	Init();
	Solve();
	return 0;
}
posted @ 2020-08-03 15:33  ♞老姚♘  阅读(202)  评论(0编辑  收藏  举报