Time Limit: 2 seconds
Memory Limit: 256 megabytes
Young wilderness explorers set off to their first expedition led by senior explorer Russell. Explorers went into a forest, set up a camp and decided to split into groups to explore as much interesting locations as possible. Russell was trying to form groups, but ran into some difficulties…
Most of the young explorers are inexperienced, and sending them alone would be a mistake. Even Russell himself became senior explorer not long ago. Each of young explorers has a positive integer parameter e i e_i ei — his inexperience. Russell decided that an explorer with inexperience e e e can only join the group of e e e or more people.
Now Russell needs to figure out how many groups he can organize. It’s not necessary to include every explorer in one of the groups: some can stay in the camp. Russell is worried about this expedition, so he asked you to help him.
The first line contains the number of independent test cases T T T( 1 ≤ T ≤ 2 ⋅ 1 0 5 1 \leq T \leq 2 \cdot 10^5 1≤T≤2⋅105). Next 2 T 2T 2T lines contain description of test cases.
The first line of description of each test case contains the number of young explorers N N N ( 1 ≤ N ≤ 2 ⋅ 1 0 5 1 \leq N \leq 2 \cdot 10^5 1≤N≤2⋅105).
The second line contains N N N integers e 1 , e 2 , … , e N e_1, e_2, \ldots, e_N e1,e2,…,eN ( 1 ≤ e i ≤ N 1 \leq e_i \leq N 1≤ei≤N), where e i e_i ei is the inexperience of the i i i-th explorer.
It’s guaranteed that sum of all N N N doesn’t exceed 3 ⋅ 1 0 5 3 \cdot 10^5 3⋅105.
Print T T T numbers, each number on a separate line.
In i i i-th line print the maximum number of groups Russell can form in i i i-th test case.
2
3
1 1 1
5
2 3 1 2 2
3
2
In the first example we can organize three groups. There will be only one explorer in each group. It’s correct because inexperience of each explorer equals to 1 1 1, so it’s not less than the size of his group.
In the second example we can organize two groups. Explorers with inexperience 1 1 1, 2 2 2 and 3 3 3 will form the first group, and the other two explorers with inexperience equal to 2 2 2 will form the second group.
This solution is not unique. For example, we can form the first group using the three explorers with inexperience equal to 2 2 2, and the second group using only one explorer with inexperience equal to 1 1 1. In this case the young explorer with inexperience equal to 3 3 3 will not be included in any group.
CodeForces 1355 B. Young Explorers
首先考虑数据范围,一共有 T T T个测试用例( 1 ≤ T ≤ 2 ⋅ 1 0 5 1 \leq T \leq 2 \cdot 10^5 1≤T≤2⋅105),每个用例有 N N N个数字 ( 1 ≤ N ≤ 2 ⋅ 1 0 5 1 \leq N \leq 2 \cdot 10^5 1≤N≤2⋅105)。
如果每个测试用例需要进行 2 ⋅ 1 0 5 2 \cdot 10^5 2⋅105次运算,那么一共需要进行 4 × 1 0 10 4 \times 10^{10} 4×1010 次运算,对比一般笔记本电脑一秒钟大约 1 0 7 10^7 107 次运算,这个算法非常容易超时。
我在一开始提交的时候,在循环中加了一个 m e m s e t memset memset 语句来初始化数组,这个函数的复杂度是 O ( l e n g t h ) O(length) O(length) 的,这里的 l e n g t h length length 表示数组长度,即 2 ⋅ 1 0 5 + 1 2 \cdot 10^5 + 1 2⋅105+1,结果就超时了。
在去掉 m e m s e t memset memset 语句以后,如果每个测试用例都对输入的 n n n 个元素进行一次遍历计算,也能够通过,应该是测试用例没有每个 N N N 都设置到 2 ⋅ 1 0 5 2 \cdot 10^5 2⋅105 这么大。不过还是推荐省去一些不必要的计算,更加稳妥一些。
在读取输入以后,先对 n n n 个数从小到大进行排序,对 l i s t [ i ] list[i] list[i] 进行遍历,用 m a r k mark mark 表示能够用来组建新队伍的人数, m a r k mark mark 初始化为1。
若 l i s t [ i ] ≤ m a r k list[i] \le mark list[i]≤mark,则 a n s = a n s + 1 ans = ans + 1 ans=ans+1, m a r k = 1 mark = 1 mark=1。
若 l i s t [ i ] > m a r k list[i] > mark list[i]>mark,则用 b u f f e r buffer buffer 存储 l i s t [ i ] − m a r k − 1 list[i] - mark - 1 list[i]−mark−1, m a r k = l i s t [ i ] mark = list[i] mark=list[i], i = i + b u f f e r i = i + buffer i=i+buffer,表示直接使用后面的人对 l i s t [ i ] list[i] list[i] 队伍要求人数进行补充,直到队伍人数满足 l i s t [ i ] list[i] list[i]要求,跳过中间 b u f f e r buffer buffer 个数,节约了一些计算。
#include
#include
#include
const int num = 2 * 1e5 + 1;
using namespace std;
int list[num];
int main()
{
int t;
int n, mark;
long long ans;
// test case
scanf("%d", &t);
// for each test case
while (t--) {
scanf("%d", &n);
// 初始化
ans = 0;
mark = 1;
// 这里不能用memset,会超时
// memset(list, 0, sizeof(list));
// 输入
for (int i = 0; i < n; i++) {
scanf("%d", &list[i]);
}
// 排序
sort(list, list + n);
// 计算
for (int i = 0; i < n; i++) {
if (list[i] <= mark) {
ans++;
mark = 1;
} else {
// 剪枝
int buffer = list[i] - mark - 1;
mark = list[i];
i += buffer;
}
}
printf("%lld\n", ans);
}
}
联系邮箱:[email protected]
CSDN:https://me.csdn.net/qq_41729780
知乎:https://zhuanlan.zhihu.com/c_1225417532351741952
公众号:复杂网络与机器学习
欢迎关注/转载,有问题欢迎通过邮箱交流。