算法刷题笔记|CodeForces 1355 B. Young Explorers 暴力剪枝


文章目录

    • 1. 题目描述
      • 1.1. Limit
      • 1.2. Problem Description
      • 1.3. Input
      • 1.4. Output
      • 1.5. Sample Input
      • 1.6. Sample Output
      • 1.7. Note
      • 1.8. Source
    • 2. 解读
    • 3. 代码

1. 题目描述 1.1. Limit
Time Limit: 2 seconds
Memory Limit: 256 megabytes
1.2. Problem Description
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 parametere i e_i ei? — his inexperience. Russell decided that an explorer with inexperiencee e e can only join the group ofe 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.
1.3. Input
The first line contains the number of independent test casesT T T( 1 ≤ T ≤ 2 ? 1 0 5 1 \leq T \leq 2 \cdot 10^5 1≤T≤2?105). Next2 T 2T 2T lines contain description of test cases.
The first line of description of each test case contains the number of young explorersN N N ( 1 ≤ N ≤ 2 ? 1 0 5 1 \leq N \leq 2 \cdot 10^5 1≤N≤2?105).
The second line containsN N N integerse 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), wheree i e_i ei? is the inexperience of thei i i-th explorer.
It’s guaranteed that sum of allN N N doesn’t exceed3 ? 1 0 5 3 \cdot 10^5 3?105.
1.4. Output
PrintT T T numbers, each number on a separate line.
Ini i i-th line print the maximum number of groups Russell can form ini i i-th test case.
1.5. Sample Input
2 3 1 1 1 5 2 3 1 2 2

1.6. Sample Output
3 2

1.7. Note
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 to1 1 1, so it’s not less than the size of his group.
In the second example we can organize two groups. Explorers with inexperience1 1 1,2 2 2 and3 3 3 will form the first group, and the other two explorers with inexperience equal to2 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 to2 2 2, and the second group using only one explorer with inexperience equal to1 1 1. In this case the young explorer with inexperience equal to3 3 3 will not be included in any group.
1.8. Source
CodeForces 1355 B. Young Explorers
2. 解读 首先考虑数据范围,一共有 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 个数,节约了一些计算。
3. 代码
#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); } }

联系邮箱:curren_wong@163.com
CSDN:https://me.csdn.net/qq_41729780
知乎:https://zhuanlan.zhihu.com/c_1225417532351741952
公众号:复杂网络与机器学习
【算法刷题笔记|CodeForces 1355 B. Young Explorers 暴力剪枝】欢迎关注/转载,有问题欢迎通过邮箱交流。
算法刷题笔记|CodeForces 1355 B. Young Explorers 暴力剪枝
文章图片

    推荐阅读