当前位置:   article > 正文

2021年北京理工大学ACM CLUB清明节组队训练赛_acm club的会员越来越多了,为此,acm club想为会员们准备一个晚会,晚会节目由会员

acm club的会员越来越多了,为此,acm club想为会员们准备一个晚会,晚会节目由会员

比赛链接

传送门

C.Corrupted Contest

题意

输入一个n表示有n个人,然后输入一个p表示有p道题,接下来输入n行表示每个人昨晚最后一题的时间的排名,问你能否找到一种做题的排序方式使得满足这样的时间排序,如果存在不能确定的情况就输出"ambiguous",否则输出每个人的做题数

解题思路

很明显这个题目是非递增的序列,并且如果后一个人的最后做出来的时间比前面一个人少的话,那么后一个人的做题的数量必然比前面那个人的做题数目少, 但是需要注意的是如果遇到时间为0的情况那么这个人做出来的题目数必然为0,我们通过差分处理一下,如果第一个时间为0的话后面都是0,直接输出就行,否则的话第一个人的做题数一定是p,然后我们按照之前的差分数组遇到-1就减少,我们最后再扫一遍结果数组,如果出现断层情况那么一定是不能确定的,那么找到了断层就直接输出"ambiguous"否则的话就直接输出我们处理的答案

Code

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 10005;
  4. int n,p,a[N],b[N],c[N];
  5. int main()
  6. {
  7. scanf("%d%d",&n,&p);
  8. for(int i = 0;i < n; ++i) {
  9. scanf("%d",&a[i]);
  10. }
  11. memset(c,-1,sizeof c);
  12. if(a[0]) {
  13. c[0] = p;
  14. }
  15. else {
  16. c[0] = 0;
  17. }
  18. c[n] = 0;
  19. for(int i = 1;i < n; ++i) {
  20. if(a[i] == 0) {
  21. c[i] = 0;
  22. continue;
  23. }
  24. if(a[i]-a[i-1] >= 0) {
  25. b[i] = 1;
  26. }
  27. else {
  28. b[i] = -1;
  29. }
  30. }
  31. for(int i = 1;i < n; ++i) {
  32. if(c[i] == 0) continue;
  33. if(b[i] == 1) {
  34. c[i] = c[i - 1];
  35. }
  36. else {
  37. c[i] = c[i - 1] - 1;
  38. }
  39. }
  40. for(int i = 1;i <= n; ++i) {
  41. if(c[i] - c[i-1] < -1) {
  42. puts("ambiguous");
  43. return 0;
  44. }
  45. }
  46. for(int i = 0;i < n; ++i) {
  47. // printf("c[%d] = %d\n",i + 1,c[i]);
  48. printf("%d\n",c[i]);
  49. }
  50. return 0;
  51. }

E.Efficiently Elevated

题意

给你一个h×w 的地图,然后给每个坐标点输入一个值,表示的是该点楼层的高度,高度为1的楼层不需要电梯,在一个楼层群中只需要建立一个最高的楼层的电梯即可,问你最少需要多少电梯

解题思路

很明显我们可以优先对楼层高的电梯周围的较低楼层进行染色,然后看染色几次就能全部满足,这个就是最少所需要的电梯数

Code

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 505;
  4. int n,m;
  5. int mp[N][N];
  6. int A[N][N];
  7. int dx[4] = {0,0,-1,1};
  8. int dy[4] = {-1,1,0,0};
  9. struct node {
  10. int x,y,h;
  11. node(int x,int y,int h) {
  12. this->x = x;
  13. this->y = y;
  14. this->h = h;
  15. }
  16. bool operator< (const node &r) const { return (h < r.h); }
  17. };
  18. void dfs(int i,int j) {
  19. if(!mp[i][j]) return;
  20. mp[i][j] = 0;
  21. for(int k = 0;k < 4; ++k) {
  22. int nx = i + dx[k];
  23. int ny = j + dy[k];
  24. if(nx > 0 && nx <= n && ny > 0 && ny <= m && A[i][j] >= A[nx][ny]) {
  25. dfs(nx,ny);
  26. }
  27. }
  28. }
  29. priority_queue<node> que;
  30. int main()
  31. {
  32. scanf("%d%d",&n,&m);
  33. for(int i = 1;i <= n; ++i) {
  34. for(int j = 1;j <= m; ++j) {
  35. scanf("%d",&mp[i][j]);
  36. A[i][j] = mp[i][j];
  37. if(mp[i][j] <= 1)
  38. mp[i][j] = 0;
  39. else
  40. mp[i][j] = 1;
  41. que.push({i,j,A[i][j]});
  42. }
  43. }
  44. int ans = 0;
  45. while(que.size()) {
  46. node p = que.top();
  47. que.pop();
  48. if(mp[p.x][p.y]) {
  49. dfs(p.x,p.y);
  50. ans++;
  51. }
  52. }
  53. printf("%d",ans);
  54. return 0;
  55. }

H.Hungry Henk

题意

输入一个n,表示有n组菜,然后对每一组菜输入一个d表示的是每一组菜有多少个菜,然后输入d个菜,问你能否找到一组菜,它的每一个菜的小写字母个数都小于等于20,然后输出这一组菜(可以输出任意满足题意的答案)

解题思路

直接暴力模拟就行,签到题

Code

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n;
  4. int main()
  5. {
  6. int d;
  7. string ch,ans="";
  8. int ansd;
  9. cin>>n;
  10. for(int i = 0;i < n; ++i) {
  11. cin>>d;
  12. ansd = d;
  13. bool fg = true;
  14. for(int j = 0;j < d; ++j) {
  15. cin>>ch;
  16. if(ch.size() > 20) fg = false;
  17. ans += ch;
  18. ans += "\n";
  19. }
  20. if(fg == true) {
  21. while(++ i < n) {
  22. cin>>d;
  23. for(int j = 0;j < d; ++j)
  24. cin>>ch;
  25. }
  26. cout<<ansd<<"\n";
  27. cout<<ans<<"\n";
  28. break;
  29. }
  30. }
  31. return 0;
  32. }

I.Incomplete Implementation

题意

输入长度为n的乱序数组(每个数都是不一样的,但是都是小于等于n的),然后你可以每次任意选择n/2个不同的下标使得他们值排序,然后有序放回这几个位置,你最多有三次操作机请问你怎么操作,会使得这个乱序数组恢复有序。(可以输出仍以方式)

解题思路

我们第一步先让 [1,n/2] 的值恢复到原位,然后再让[n/4+1,n/2]恢复到原位,最后直接输出剩下的n/2个数,即可完成排序,值得注意的是,当我们再处理前两种的情况有可能会有这样的情况,那个数本来就在自己的位置,那么我们就需要找一些其他位置的数来凑成n/2个数,我们应该从1开始往后选择,因为我们是优先对前面处理,也就是前面的数字不会影响我们对排序的处理

Code

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 100005;
  4. int n,a[N],b[N];
  5. set<int> ans;
  6. int main()
  7. {
  8. scanf("%d",&n);
  9. for(int i = 1;i <= n; ++i) {
  10. scanf("%d",&a[i]);
  11. b[a[i]] = i;
  12. }
  13. printf("%d\n",3);
  14. ans.clear();
  15. for(int i = 1;i <= n/4; ++i) {
  16. int a1 = b[i];
  17. int a2 = i;
  18. if(a1 == a2) {
  19. a2 = n;
  20. }
  21. else {
  22. b[a[i]] = a1;
  23. b[i] = i;
  24. int temp = a[a1];
  25. a[a1] = a[a2];
  26. a[a2] = temp;
  27. }
  28. ans.insert(a1);
  29. ans.insert(a2);
  30. }
  31. int i = 1;
  32. while(ans.size() < n / 2) {
  33. ans.insert(i++);
  34. }
  35. for(auto it : ans) {
  36. printf("%d ",it);
  37. }
  38. puts("");
  39. ans.clear();
  40. // for(int i = 1;i <= n; ++i) printf("%d%c",a[i],i==n?'\n':' ');
  41. // for(int i = 1;i <= n; ++i) printf("%d%c",b[i],i==n?'\n':' ');
  42. // for(int i = 1;i <= n; ++i) b[a[i]] = i;
  43. for(int i = n/4 + 1;i <= n/2; ++i) {
  44. int a1 = b[i];
  45. int a2 = i;
  46. if(a1 == a2) {
  47. a2 = n;
  48. }
  49. else {
  50. b[a[i]] = a1;
  51. b[i] = i;
  52. int temp = a[a1];
  53. a[a1] = a[a2];
  54. a[a2] = temp;
  55. }
  56. ans.insert(a1);
  57. ans.insert(a2);
  58. }
  59. i = 1;
  60. while(ans.size() < n / 2) {
  61. ans.insert(i++);
  62. }
  63. for(auto it : ans) {
  64. printf("%d ",it);
  65. }
  66. puts("");
  67. // for(int i = 1;i <= n; ++i) b[a[i]] = i;
  68. for(int i = n/2+1;i <= n; ++i) {
  69. printf("%d%c",a[i],i==n?'\n':' ');
  70. }
  71. // for(int i = 1;i <= n; ++i) {
  72. // printf("%d ",a[i]);
  73. // }
  74. return 0;
  75. }

J.Jigsaw

题意

给你拼图的一些碎片,角落的碎片数为c,边缘的碎片数为e,中间的碎片数为m,问你能否用尽这些碎片拼出一个图,如果可以的话就输出最后拼图的长和宽,否则输出“impossible”

解题思路

很明显如果角落的c不为4,那么一定不能满足条件,然后如果e不能被2整除那么一定不能满足条件,最后就是计算长和宽了,这里我们设内矩形的长和宽为a,b

(a+b)×2=e
a×b=m

然后可以得到一个一元二次方程,注意的是,解可能有两种,所以我们两种都要考虑

Code

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define int long long
  4. int c,e,m;
  5. signed main()
  6. {
  7. cin>>c>>e>>m;
  8. if(c == 4) {
  9. if(e % 2 == 0) {
  10. int a1,a2,b1,b2;
  11. a1 = (e + sqrt((e*e-16.0*m)))/4.0;
  12. a2 = (e - sqrt((e*e-16.0*m)))/4.0;
  13. b1 = (e/2)-a1;
  14. b2 = (e/2)-a2;
  15. if(a1 * b1 == m) {
  16. printf("%lld %lld\n",a1+2,b1+2);
  17. }
  18. else if(a2 * b2 == m) {
  19. printf("%lld %lld\n",a2+2,b2+2);
  20. }
  21. else {
  22. puts("impossible");
  23. }
  24. }
  25. else {
  26. puts("impossible");
  27. }
  28. }
  29. else {
  30. puts("impossible");
  31. }
  32. return 0;
  33. }

感想

被各位大佬暴捶……这个绝望小学我可能一被子都忘不掉(


打下来除了E题一直读错题,rhr写了一发wa了,然后我按照他的理解写了一发然后又wa了,然后我又去读题,感觉还是没懂,结果比赛结束发现是真的读错题了,想起了yy在比赛的时候想了个反例我按照rhr的想法,就直接否定了……,然后最后半小时就一直挂机

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/443309
推荐阅读
相关标签
  

闽ICP备14008679号