AtCoder入门练习题B--题解报告

刺骨的言语ヽ痛彻心扉 2022-05-27 02:07 280阅读 0赞

一、题目

https://practice.contest.atcoder.jp/tasks/practice_2

二、分析

这里有三组测试用例。

第一组N = 26, Q = 1000。因为N * N < Q,所以可用冒泡排序法。具体代码参考官方给的Sample Code。

第二组N = 26, Q = 100,由于询问次数只有100次,可用插入排序法处理。每插入一个数据前,先用二分查找法查找插入的位置,这样可提升排序速度。但是这样需要询问26log226次,还是不能通过所有的数据。这就要求我们需要对每一次询问的答案做一个记忆化处理,记录下小球的质量关系,然后根据这个质量关系就可以得出有序的数列,从而降低时间复杂度。

第三组N=5, Q=7。先比较第0个和第1个,第2个和第3个,第1个和第3个,再求第5个的位置,最后求第2个和第0个、第1个、第5个的位置关系。

三、代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. char s[29], ans[29];
  4. int cmp['Z'+5]['Z'+5];
  5. int cnt = 0;
  6. // 比较两个字符,如果a>b返回true,如果a<b返回false
  7. bool cmp_char(const char a, const char b)
  8. {
  9. char cp;
  10. if(cmp[a][b] == -1)
  11. {
  12. printf("? %c %c\n", a, b);
  13. fflush(stdout);
  14. scanf(" %c", &cp);
  15. if(cp == '>')
  16. {
  17. cmp[a][b] = true;
  18. cmp[b][a] = false;
  19. return true;
  20. }
  21. else
  22. {
  23. cmp[a][b] = false;
  24. cmp[b][a] = true;
  25. return false;
  26. }
  27. }
  28. return cmp[a][b];
  29. }
  30. // N为5时,调用此方法进行排序
  31. void sort_N5(char c)
  32. {
  33. if(cmp_char(c, s[1]))
  34. {
  35. if(cmp_char(c, s[2]))
  36. {
  37. s[3] = c;
  38. }
  39. else
  40. {
  41. s[3] = s[2];
  42. s[2] = c;
  43. }
  44. }
  45. else
  46. {
  47. if(cmp_char(c, s[0]))
  48. {
  49. s[3] = s[2];
  50. s[2] = s[1];
  51. s[1] = c;
  52. }
  53. else
  54. {
  55. s[3] = s[2];
  56. s[2] = s[1];
  57. s[1] = s[0];
  58. s[0] = c;
  59. }
  60. }
  61. }
  62. // N为26时,调用此方法进行排序
  63. void sort_N26(char c)
  64. {
  65. int l = 0, r = cnt;
  66. while(l < r)
  67. {
  68. int mid = (l + r) >> 1;
  69. if(cmp_char(c, ans[mid]))
  70. {
  71. l = mid + 1;
  72. }
  73. else
  74. {
  75. r = mid;
  76. }
  77. }
  78. cnt++;
  79. // 在新加入的c比原先的所有字符都大时,if条件成立
  80. // 比如原先的顺序为"AB",新加和的"C"比"B"大,即"AB"变为"ABC"时
  81. if(cmp_char(c, ans[r]))
  82. {
  83. r++;
  84. }
  85. for(int i = cnt; i >= r + 1; i--)
  86. {
  87. ans[i] = ans[i-1];
  88. }
  89. ans[r] = c;
  90. }
  91. int main()
  92. {
  93. int N, Q;
  94. scanf("%d%d", &N, &Q);
  95. for(int i = 0; i < 26; i++)
  96. {
  97. s[i] = (char)(i + 'A');
  98. }
  99. s[N] = '\0';
  100. memset(cmp, -1, sizeof(cmp));
  101. if(N == 26) // Q=1000, 或Q=100
  102. {
  103. cnt = 0;
  104. ans[0] = s[0];
  105. ans[N] = '\0';
  106. for(int i = 1; i < N; i++)
  107. {
  108. sort_N26(s[i]);
  109. }
  110. printf("! %s\n", ans);
  111. }
  112. else // N=5, Q=7
  113. {
  114. if(cmp_char(s[0], s[1]))
  115. {
  116. swap(s[0], s[1]);
  117. }
  118. if(cmp_char(s[2], s[3]))
  119. {
  120. swap(s[2], s[3]);
  121. }
  122. if(cmp_char(s[1], s[3]))
  123. {
  124. swap(s[0], s[2]);
  125. swap(s[1], s[3]);
  126. }
  127. /* * 至此,s[0]<s[1], s[2]<s[3], s[1]<s[3] * 还有两个问题: * s[5]放哪;s[2]与s[0]、s[1]谁大谁小 */
  128. char temp = s[2];
  129. if(cmp_char(s[4], s[1]))
  130. {
  131. // 若s[4]>s[1],则比较s[4]与s[3]
  132. if(cmp_char(s[4], s[3]))
  133. {
  134. // s[4]>s[1], s[4]>s[3]
  135. // 把0、1、2、5这四个位置填满,便于调用sort_N5()
  136. s[2] = s[3];
  137. }
  138. else
  139. {
  140. // s[1]<s[4]<s[3]
  141. s[2] = s[4];
  142. s[4] = s[3];
  143. }
  144. }
  145. else
  146. {
  147. // 若s[4]<s[1],则比较s[4]与s[0]
  148. if(cmp_char(s[4], s[0]))
  149. {
  150. // s[0]<s[4]<s[1]
  151. s[2] = s[1];
  152. s[1] = s[4];
  153. s[4] = s[3];
  154. }
  155. else
  156. {
  157. // s[4]<s[0]<s[1]
  158. s[2] = s[1];
  159. s[1] = s[0];
  160. s[0] = s[4];
  161. s[4] = s[3];
  162. }
  163. }
  164. sort_N5(temp);
  165. printf("! %s\n", s);
  166. }
  167. return 0;
  168. }

四、参考

https://www.cnblogs.com/TheRoadToAu/p/8463454.html

更多内容请关注微信公众号
wechat\_public.jpg重点内容

发表评论

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

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

相关阅读