题目翻译
这个题的大致思路和下面这道题很相似P7260 [COCI2009-2010#3] RAZGOVOR - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
因此在题解【洛谷】 P7260 [COCI2009-2010#3] RAZGOVOR-CSDN博客中出现的思路不予重复,只分析一下如何将这个题转化为上述问题。
思路转换
这道题和PAZGOVER很像很像,但是这题目给出的所有数字所在的区间不一定是连续的。比如所有数字所在的区间可能是 ,此种情况下,无法直接使用P7260的代码。
另外,对于此题的数据范围,不难发现玩具的数字大小为 ~ ,如果还使用数组来计数的话一定会爆栈。
不难想到,可以利用stl中map的特性,来完成此题:map可以对容器内部的数据按照first的大小进行排序,利用这个特性,我们就可以在nlogn的时间复杂度内得到有序的(位置,数量)二元组,之后需要解决的问题是二元组的不连续的问题。
我们指导,只有位置是连续的,才可以使用P7260的写法,所以现在需要将非连续的二元组转化为"连续"的二元组,这里可以利用map遍历扩充vector数组来实现,受空间限制,不能将每一个没有出现的数字都添加到vector数组当中,但对于一连串的未出现的0,可以用一个0来替代,这样的效果都是一样的。
AC代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = 2 * N;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int hash_num = 131;
const double eps = 1e-6;
const double pi = acos(-1);
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef long double LD;
int n, m;
map<int, int> dic;
vector<PII> b(M);
int main()
{
int t;
scanf("%d", &t);
while(t --)
{
dic.clear();
b.clear();
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
{
int x;
scanf("%d", &x);
dic[x] ++;
}
b.push_back({0, 0});
for(auto t : dic)
{
int x = t.first, y = t.second;
if(x != b.back().first + 1) b.push_back({b.back().first + 1, 0});
b.push_back(t);
}
LL cnt = 0;
int tmp = 0;
for(auto t : b)
{
int tt = t.second;
if(tt > tmp) cnt += tt - tmp;
tmp = tt;
}
cout << cnt << endl;
}
}