2022-05-27每日刷题打卡
代码源——每日一题
题目背景
鶸尛鱻养了许多兔纸。
题目描述
众所周知,兔纸是一种神奇的生物,它有许多种毛色。
鶸尛鱻一共有 n 只兔纸,它们从左到右排成一排,第 i 只兔纸的毛色为 coli。
兔纸们十分活跃,时常会与旁边的兔纸交换位置。
五颜六色的兔纸弄得鶸尛鱻眼花缭乱,他想统计区间 [l,r] 内兔纸的颜色,但他的数学很差,你可以帮帮他吗?
输入格式
第 1 行两个正整数 n,m 分别表示兔纸数量和操作次数。
第 2 行 n 个正整数 col1,col2,…,coln,表示初始状态下从左到右每只兔纸的颜色。
此后 m 行,每行输入格式为 1 x 或 2 l r c,其中 {1/2} 表示操作类型。
操作 1 为 交换 操作,表示第 x 只兔纸和第 x+1 只兔纸交换位置。
操作 2 为 查询 操作,询问当前区间 [l,r] 内有多少只颜色为 c 的兔纸。
输出格式
对于每个操作 2,你需要输出一行一个自然数作为答案。
样例输入
7 9
8 7 6 6 7 8 3
1 5
1 4
2 1 7 7
1 6
1 4
2 3 6 8
2 1 3 7
2 1 2 6
2 2 5 7
样例输出
2
1
1
0
1
数据范围
对于全部测试数据,满足 2≤n≤3×105,1≤m,coli,c≤3×105,且保证 1≤x<n,1≤l<r≤n。
问题解析
一开始写的线段树,但是t了,后来看大佬做法发现vector或者普通二维数组就可以了。
按照颜色分类,一个颜色一个数组v,每个数组存的是这个颜色在原数组的下标。
操作1:我们先看原数组x和x+1这两个位置的颜色是否一样,如果一样就没必要换了,如果不一样,我们先根据x的颜色在数组v里找到他对应的元素,因为我们的元素存的是位置,x和x+1就相当于位于x的元素移动到x+1去了,那么我们把v数组里的对应元素++即可。然后找x+1,同理x+1移动到x去了,那么我们直接把v数组对应元素–即可。查找元素这两步可以用二分,如果用的vector写那就用自带的lower就可以,如果是普通数组就要手写二分了。
操作2:我们在颜色c的数组v里,二分找大小在lr的元素,找到多少个就说明lr区间有多少个颜色为c的元素。
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n'
#define int ll
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6;
int a[N];
vector<int>v[N];
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
v[a[i]].push_back(i);
}
int st, l, r, c;
while (m--)
{
cin >> st;
if (st == 1)
{
cin >> c;
if (a[c] == a[c + 1])continue;
int x = lower_bound(v[a[c]].begin(), v[a[c]].end(), c) - v[a[c]].begin();
v[a[c]][x]++;
int y = lower_bound(v[a[c + 1]].begin(), v[a[c + 1]].end(), c + 1) - v[a[c + 1]].begin();
v[a[c + 1]][y]--;
swap(a[c], a[c + 1]);
}
else
{
cin >> l >> r >> c;
int x = lower_bound(v[c].begin(), v[c].end(), l) - v[c].begin();
int y = upper_bound(v[c].begin(), v[c].end(), r) - v[c].begin() - 1;
if (x > y)cout << 0 << endl;
else cout << y - x + 1 << endl;
}
}
return 0;
}