当前位置:   article > 正文

Codeforces Round #956 (Div. 2) and ByteRace 2024(A~D题解)

codeforces round #956 (div. 2) and byterace 2024

这次比赛也是比较吃亏的,做题顺序出错了,先做的第三个,错在第三个数据点之后,才做的第二个(因为当时有个地方没检查出来)所以这次比赛还是一如既往地打拉了

那么就来发一下题解吧

A. Array Divisibility

题意:对于1<=k<=n,对于每个k其倍数下标之和一定为k的倍数

思路:直接从1赋值到n就行,也是水题一个

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define int long long
  4. int t;
  5. int n;
  6. signed main()
  7. {
  8. cin>>t;
  9. while(t--)
  10. {
  11. cin>>n;
  12. for(int i=1;i<=n;i++)
  13. {
  14. cout<<i<<" ";
  15. }
  16. cout<<"\n";
  17. }
  18. return 0;
  19. }

B. Corner Twist

题意:就是给你两个数组,问你两个数组能否按照题上所说的方法相互转换得到

思路:将整个大矩阵拆成2*2的小矩阵,然后每次只要让左上角那个和下面的变成一样就可以,然后我们最后原本只需要检查最后一列和最后一行是否相同就可以(ps:我写的是逐一比较,因为比较好写)(错了一次是因为比较的时候内层循环写成n了)

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define int long long
  4. int t;
  5. int n,m;
  6. char a[505][505];
  7. char b[505][505];
  8. signed main()
  9. {
  10. cin>>t;
  11. while(t--)
  12. {
  13. cin>>n>>m;
  14. for(int i=1;i<=n;i++)
  15. {
  16. for(int j=1;j<=m;j++)
  17. {
  18. cin>>a[i][j];
  19. }
  20. }
  21. for(int i=1;i<=n;i++)
  22. {
  23. for(int j=1;j<=m;j++)
  24. {
  25. cin>>b[i][j];
  26. }
  27. }
  28. for(int i=1;i<=n-1;i++)
  29. {
  30. for(int j=1;j<=m-1;j++)
  31. {
  32. int cha = ((b[i][j]-'0')-(a[i][j]-'0')+3)%3;
  33. if(cha==1)
  34. {
  35. a[i][j]=(a[i][j]+1)%3+'0';
  36. a[i+1][j+1]=(a[i+1][j+1]+1)%3+'0';
  37. a[i+1][j]=(a[i+1][j]+2)%3+'0';
  38. a[i][j+1]=(a[i][j+1]+2)%3+'0';
  39. }
  40. else if(cha==2)
  41. {
  42. a[i][j]=(a[i][j]+2)%3+'0';
  43. a[i+1][j+1]=(a[i+1][j+1]+2)%3+'0';
  44. a[i+1][j]=(a[i+1][j]+1)%3+'0';
  45. a[i][j+1]=(a[i][j+1]+1)%3+'0';
  46. }
  47. }
  48. }
  49. int flag=1;
  50. for(int i=1;i<=n;i++)
  51. {
  52. for(int j=1;j<=m;j++)
  53. {
  54. if(a[i][j]==b[i][j])
  55. {
  56. continue;
  57. }
  58. else
  59. flag=0;
  60. }
  61. }
  62. if(flag==0)
  63. {
  64. cout<<"NO"<<"\n";
  65. }
  66. else
  67. {
  68. cout<<"YES"<<"\n";
  69. }
  70. }
  71. return 0;
  72. }

 C. Have Your Cake and Eat It Too

题意:就说有一个蛋糕 ,被分成了许多块,然后三个人对每部分的蛋糕都有一个自己的价值,但是所有块的价值总和是一定的,然后问你如何划分这个区间,才能满足每个区间都大于(tot+2)/3

思路:对六种情况分别贪心即可,先让两边的取到比sum大的位置,然后再看中间的是否比sum大,是的话就直接输出,如果都不满足,最后就只能输出-1了

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define int long long
  4. signed main()
  5. {
  6. int t;
  7. cin>>t;
  8. while(t--)
  9. {
  10. int n;
  11. cin >> n;
  12. int a[n+1], b[n+1], c[n+1];
  13. int sum = 0;
  14. for(int i = 1;i<=n;i++)
  15. {
  16. cin >> a[i];
  17. sum += a[i];
  18. }
  19. sum = (sum+2)/3;//题中说了上限除法
  20. for(int i = 1;i<=n;i++)
  21. {
  22. cin >> b[i];
  23. }
  24. for(int i = 1;i<=n;i++)
  25. {
  26. cin >> c[i];
  27. }
  28. vector<int> p1(n+5), p2(n+5), p3(n+5);//正序前缀和
  29. vector<int> s1(n+5), s2(n+5), s3(n+5);//倒序前缀和
  30. for(int i = 1; i <= n; i++)
  31. {
  32. p1[i] = p1[i-1] + a[i];
  33. p2[i] = p2[i-1] + b[i];
  34. p3[i] = p3[i-1] + c[i];
  35. }
  36. for(int i = n; i >= 1; i--)
  37. {
  38. s1[i] = s1[i+1] + a[i];
  39. s2[i] = s2[i+1] + b[i];
  40. s3[i] = s3[i+1] + c[i];
  41. }
  42. //a b c
  43. int i = 1, j = n;
  44. while(p1[i-1] < sum && i <= n)
  45. {
  46. i++;
  47. }
  48. while(s3[j+1] < sum && j >= 1)
  49. {
  50. j--;
  51. }
  52. if(i <= j && p2[j]-p2[i-1] >= sum)
  53. {
  54. cout << 1 << ' ' << i-1 << ' ' << i << ' ' << j << ' ' << j+1 << ' ' << n << endl;
  55. continue;
  56. }
  57. // a c b
  58. i = 1, j = n;
  59. while(p1[i-1] < sum && i <= n)
  60. {
  61. i++;
  62. }
  63. while(s2[j+1] < sum && j >= 1)
  64. {
  65. j--;
  66. }
  67. if(i <= j && p3[j]-p3[i-1] >= sum)
  68. {
  69. cout << 1 << ' ' << i-1 << ' ' << j+1 << ' ' << n << ' ' << i << ' ' << j << endl;
  70. continue;
  71. }
  72. // b c a
  73. i = 1, j = n;
  74. while(p2[i-1] < sum && i <= n)
  75. {
  76. i++;
  77. }
  78. while(s1[j+1] < sum && j >= 1)
  79. {
  80. j--;
  81. }
  82. if(i <= j && p3[j]-p3[i-1] >= sum)
  83. {
  84. cout << j+1 << ' ' << n << ' ' << 1 << ' ' << i-1 << ' ' << i << ' ' << j << endl;
  85. continue;
  86. }
  87. // b a c
  88. i = 1, j = n;
  89. while(p2[i-1] < sum && i <= n)
  90. {
  91. i++;
  92. }
  93. while(s3[j+1] < sum && j >= 1)
  94. {
  95. j--;
  96. }
  97. if(i <= j && p1[j]-p1[i-1] >= sum)
  98. {
  99. cout << i << ' ' << j << ' ' << 1 << ' ' << i-1 << ' ' << j+1 << ' ' << n << endl;
  100. continue;
  101. }
  102. // c a b
  103. i = 1, j = n;
  104. while(p3[i-1] < sum && i <= n)
  105. {
  106. i++;
  107. }
  108. while(s2[j+1] < sum && j >= 1)
  109. {
  110. j--;
  111. }
  112. if(i <= j && p1[j]-p1[i-1] >= sum)
  113. {
  114. cout << i << ' ' << j << ' ' << j+1 << ' ' << n << ' ' << 1 << ' ' << i-1 << endl;
  115. continue;
  116. }
  117. // c b a
  118. i = 1, j = n;
  119. while(p3[i-1] < sum && i <= n)
  120. {
  121. i++;
  122. }
  123. while(s1[j+1] < sum && j >= 1)
  124. {
  125. j--;
  126. }
  127. if(i <= j && p2[j]-p2[i-1] >= sum)
  128. {
  129. cout << j+1 << ' ' << n << ' ' << i << ' ' << j << ' ' << 1 << ' ' << i-1 << endl;
  130. continue;
  131. }
  132. cout << -1 << endl;
  133. }
  134. return 0;
  135. }

D. Swap Dilemma

 

 

题意:就是说给你两个数组,然后每次再a数组选两个坐标,b数组选两个坐标,然后各自再各自的数组交换,然后问你最后两个数组能不能变成一样的

思路:这题我想到了两种做法

逆序对

(1)逆序对的方法,众所周知,在大学有一门神奇的科目叫做线性代数,线性代数里面讲过一个东西叫做逆序对,只有逆序对的个数为同一奇偶性,才有可能相同,因为a,b数组每次都要变换一次,所以他们的奇偶性一定是都会在每一次变化,所以我们需要统计奇偶性,然后来判断,当然了,在之前还需要判断元素种类是否相同,如果个数不同一定为no

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define int long long
  4. int mergeSort(vector<int> &nums, int left, int right)
  5. {
  6. if (left >= right) {
  7. return 0;
  8. }
  9. int mid = left + (right - left) / 2;
  10. int count = mergeSort(nums, left, mid) + mergeSort(nums, mid + 1, right);
  11. vector<int> tmp(right - left + 1);
  12. int i = left, j = mid + 1, k = 0;
  13. while (i <= mid && j <= right) {
  14. if (nums[i] <= nums[j]) {
  15. tmp[k++] = nums[i++];
  16. } else {
  17. tmp[k++] = nums[j++];
  18. count += mid - i + 1; // 计算逆序数
  19. }
  20. }
  21. while (i <= mid) {
  22. tmp[k++] = nums[i++];
  23. }
  24. while (j <= right) {
  25. tmp[k++] = nums[j++];
  26. }
  27. for (int p = 0; p < tmp.size(); ++p) {
  28. nums[left + p] = tmp[p];
  29. }
  30. return count;
  31. }
  32. int solve(vector<int> &nums)
  33. {
  34. if (nums.size() <= 1) {
  35. return 0;
  36. }
  37. return mergeSort(nums, 0, nums.size() - 1);
  38. }
  39. void solve()
  40. {
  41. map<int,int> mp;
  42. int n;
  43. cin >> n;
  44. vector<int> a(n+2);
  45. vector<int> b(n+2);
  46. for (int i=1;i<=n;i++)
  47. cin >> a[i];
  48. for (int i=1;i<=n;i++)
  49. {
  50. cin >> b[i];
  51. mp[b[i]]=i;
  52. }
  53. for(int i=1;i<=n;i++)
  54. {
  55. if(mp.count(a[i])==0)
  56. {
  57. cout<<"NO\n";
  58. return ;
  59. }
  60. }
  61. int ans1=solve(a),ans2=solve(b);
  62. if (ans1%2 ==ans2%2)
  63. cout << "YES\n";
  64. else
  65. cout << "NO\n";
  66. }
  67. signed main()
  68. {
  69. int t;
  70. cin >> t;
  71. while (t--)
  72. solve();
  73. return 0;
  74. }

 交换次数法

(2)那么来讲另一种比较简单的方法,交换次数来判断,因为题目上所说每次两个数组都要交换,那么我们就只交换一个,然后统计变成另一个的次数为多少,是偶数就是yes是奇数就是no

当然了,在之前也是需要判断种类是否相同的

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define int long long
  4. int a[200005], b[200005];
  5. map<int, int> mp;
  6. void solve()
  7. {
  8. mp.clear();
  9. int n;
  10. cin >> n;
  11. for (int i=1;i<=n;i++)
  12. cin >> a[i];
  13. for (int i=1;i<=n;i++)
  14. {
  15. cin >> b[i];
  16. mp[b[i]]=i;
  17. }
  18. int ans = 0;
  19. for (int i=1;i<=n;i++)
  20. {
  21. if (b[i] == a[i])
  22. continue;
  23. if (mp.count(a[i]) == 0)
  24. {
  25. cout << "NO\n";
  26. return;
  27. }
  28. int p=mp[a[i]];
  29. swap(b[i],b[p]);
  30. mp[b[i]]=i;
  31. mp[b[p]]=p;
  32. ans+=1;
  33. }
  34. if (ans%2 == 0)
  35. cout << "YES\n";
  36. else
  37. cout << "NO\n";
  38. }
  39. signed main()
  40. {
  41. int t;
  42. cin >> t;
  43. while (t--)
  44. solve();
  45. return 0;
  46. }

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

闽ICP备14008679号