【二分优化】Preparing for Merge Sort CodeForces - 847B

「爱情、让人受尽委屈。」 2022-06-05 11:47 126阅读 0赞

Think:
1知识点:二分优化
2题意:输入一个长度最长可达到2e5的序列,序列中的每一个数各不相同,要求按照步骤分组,分组步骤为:
(1):从左到右在序列中选取第一个未使用的数
(2):从(1)步找到的数开始向右继续寻找,每次选取一个未使用的且大于前一个被选取的数的数
(3):若无法进行第(1)步即序列中元素已全部分组,结束分组;
若无法进行第(2)步,进行下一次分组;
3解题思路:
(1):for循环暴力模拟(一个小组一个小组的选取)——超时
(2):每次选择序列中的当前元素,试探是否可以放置在之前已经分好的小组,若可以,放置更新,若不可以,开新的小组进行放置——(暴力查询放置小组——超时)——(通过数据查询临界情况优化暴力查询放置小组——1216msAccepted)——(临界情况优化+二分优化查询放置小组——139msAccepted)

vjudge题目链接

以下为Accepted代码——(通过数据查询临界情况优化暴力查询放置小组——1216msAccepted)

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <vector>
  5. using namespace std;
  6. vector <int> v1[204014];
  7. vector <int>:: iterator it;
  8. int rec[204014];
  9. int main(){
  10. int n, i, j, k, t;
  11. scanf("%d", &n);
  12. for(i = 0; i < n; i++)
  13. scanf("%d", &rec[i]);
  14. k = 0;
  15. v1[k++].push_back(rec[0]);
  16. for(i = 1; i < n; i++){
  17. if(k > 0){
  18. t = v1[k-1].back();
  19. if(t > rec[i]){
  20. v1[k].push_back(rec[i]);
  21. k++;
  22. continue;
  23. }
  24. }
  25. for(j = 0; j < k; j++){
  26. t = v1[j].back();
  27. if(t < rec[i]){
  28. v1[j].push_back(rec[i]);
  29. break;
  30. }
  31. }
  32. }
  33. for(i = 0; i < k; i++){
  34. for(it = v1[i].begin(); it != v1[i].end(); it++){
  35. if(it != v1[i].begin()) printf(" ");
  36. printf("%d", *it);
  37. }
  38. printf("\n");
  39. }
  40. return 0;
  41. }

以下为Accepted代码——(临界情况优化+二分优化查询放置小组——139msAccepted)

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. struct Node{
  6. int x;
  7. int id;
  8. bool operator < (const Node &b) const{
  9. if(id == b.id) return x < b.x;
  10. return id < b.id;
  11. }
  12. }rec[204014];
  13. int grou[204014];
  14. int main(){
  15. int n, i, k, l, r, mid;
  16. while(~scanf("%d", &n)){
  17. for(i = 0; i < n; i++){
  18. scanf("%d", &rec[i].x);
  19. }
  20. k = 0;
  21. grou[k++] = rec[0].x;
  22. rec[0].id = 0;
  23. for(i = 1; i < n; i++){
  24. if(grou[k-1] > rec[i].x){
  25. grou[k++] = rec[i].x;
  26. rec[i].id = k-1;
  27. continue;
  28. }
  29. l = 0, r = k-1;
  30. while(l <= r){
  31. mid = (l+r)>>1;
  32. if(mid == 0 && grou[mid] < rec[i].x){
  33. grou[mid] = rec[i].x;
  34. rec[i].id = mid;
  35. break;
  36. }
  37. else if(mid > 0 && grou[mid] < rec[i].x && grou[mid-1] > rec[i].x){
  38. grou[mid] = rec[i].x;
  39. rec[i].id = mid;
  40. break;
  41. }
  42. else if(grou[mid] > rec[i].x){
  43. l = mid+1;
  44. }
  45. else if(mid > 0 && grou[mid-1] < rec[i].x){
  46. r = mid-1;
  47. }
  48. }
  49. }
  50. sort(rec, rec+n);
  51. for(i = 0; i < n; i++){
  52. printf("%d", rec[i].x);
  53. if(i == n-1 || rec[i].id < rec[i+1].id) printf("\n");
  54. else printf(" ");
  55. }
  56. }
  57. return 0;
  58. }

发表评论

表情:
评论列表 (有 0 条评论,126人围观)

还没有评论,来说两句吧...

相关阅读

    相关 merge_sort

    并排序是一种基于归并方法的排序。所谓归并是指将两个或两个以上的有序表合成一个新的有序表,包含所有元素。 利用归并思想进行排序,可这样实现:首先将整个表看成是n个有序子表...

    相关 归并排序(merge sort

    归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。(出自[维基百科][Li