当前位置:   article > 正文

Educational Codeforces Round 166 (Rated for Div. 2) (C、D)

educational codeforces round 166 (rated for div. 2)

1976C - Job Interview 

        题意:

        思路:考虑求出如果多一个程序员,那么整个序列该怎么选,多一个测试员,整个序列该怎么选。那么若第i个人原先是程序员,那么他不来面试以后后面的所有人选择情况就是多一个程序员的情况。同理,若第i个人原先是测试员,那么他不来面试以后后面所有人选择情况就是多一个测试员的选择情况。然后考虑用前缀和来快速求解。

        

  1. // Problem: C. Job Interview
  2. // Contest: Codeforces - Educational Codeforces Round 166 (Rated for Div. 2)
  3. // URL: https://codeforces.com/contest/1976/problem/C
  4. // Memory Limit: 256 MB
  5. // Time Limit: 2000 ms
  6. //
  7. // Powered by CP Editor (https://cpeditor.org)
  8. #include <bits/stdc++.h>
  9. using namespace std;
  10. #define LL long long
  11. #define pb push_back
  12. #define x first
  13. #define y second
  14. #define endl '\n'
  15. const LL maxn = 4e05+7;
  16. const LL N = 5e05+10;
  17. #define int long long
  18. const LL mod = 1e09+7;
  19. const int inf = 0x3f3f3f3f;
  20. const LL llinf = 5e18;
  21. typedef pair<int,int>pl;
  22. priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
  23. priority_queue<LL> ma;//大根堆
  24. LL gcd(LL a, LL b){
  25. return b > 0 ? gcd(b , a % b) : a;
  26. }
  27. LL lcm(LL a , LL b){
  28. return a / gcd(a , b) * b;
  29. }
  30. int n , m;
  31. vector<int>a(N , 0);
  32. void init(int n){
  33. for(int i = 0 ; i <= n ; i ++){
  34. a[i] = 0;
  35. }
  36. }
  37. void solve()
  38. {
  39. int n , m;
  40. cin >> n >> m;
  41. int a[n + m + 1];
  42. int b[n + m + 1];
  43. int res1 = n , res2 = m;
  44. for(int i = 0 ; i < n + m + 1; i ++){
  45. cin >> a[i];
  46. }
  47. for(int i = 0 ; i < n + m + 1; i ++){
  48. cin >> b[i];
  49. }
  50. vector<int>val(n + m + 1 , 0);
  51. vector<int>ans(n + m + 1 , 0);
  52. vector<int>cntt(n + m + 1 , 0);//正常分配
  53. vector<int>cntt1(n + m + 1 , 0);//前面少一个程序员
  54. vector<int>cntt2(n + m + 1 , 0);//前面少一个测试员
  55. int cnt = 0;
  56. for(int i = 0 ; i < n + m ; i ++){
  57. if(a[i] > b[i] && res1 > 0){
  58. cnt += a[i];
  59. res1 --;
  60. val[i] = 1;
  61. }
  62. else if(a[i] > b[i]){
  63. cnt += b[i];
  64. res2 --;
  65. val[i] = 2;
  66. }
  67. if(a[i] < b[i] && res2 > 0){
  68. cnt += b[i];
  69. res2--;
  70. val[i] = 2;
  71. }
  72. else if(a[i] < b[i]){
  73. cnt += a[i];
  74. res1--;
  75. val[i] = 1;
  76. }
  77. cntt[i] = cnt;
  78. }
  79. ans[n + m] = cnt;
  80. res1 = n + 1 , res2 = m;
  81. cnt = 0;
  82. for(int i = 0 ; i < n + m + 1 ; i ++){
  83. if(a[i] > b[i] && res1 > 0){
  84. cnt += a[i];
  85. res1 --;
  86. }
  87. else if(a[i] > b[i]){
  88. cnt += b[i];
  89. res2 --;
  90. }
  91. if(a[i] < b[i] && res2 > 0){
  92. cnt += b[i];
  93. res2--;
  94. }
  95. else if(a[i] < b[i]){
  96. cnt += a[i];
  97. res1--;
  98. }
  99. cntt1[i] = cnt;
  100. }
  101. res1 = n , res2 = m + 1;
  102. cnt = 0;
  103. for(int i = 0 ; i < n + m + 1 ; i ++){
  104. if(a[i] > b[i] && res1 > 0){
  105. cnt += a[i];
  106. res1 --;
  107. }
  108. else if(a[i] > b[i]){
  109. cnt += b[i];
  110. res2 --;
  111. }
  112. if(a[i] < b[i] && res2 > 0){
  113. cnt += b[i];
  114. res2--;
  115. }
  116. else if(a[i] < b[i]){
  117. cnt += a[i];
  118. res1--;
  119. }
  120. cntt2[i] = cnt;
  121. }
  122. for(int i = 0 ; i < n + m ; i ++){
  123. int anss = 0;
  124. if(val[i] == 1){
  125. anss += cntt1[n + m] - cntt1[i];
  126. }
  127. else if(val[i] == 2){
  128. anss += cntt2[n + m] - cntt2[i];
  129. }
  130. if(i != 0)
  131. anss += cntt[i - 1];
  132. cout << anss << " ";
  133. }
  134. cout << ans[n + m] << endl;
  135. }
  136. signed main()
  137. {
  138. ios::sync_with_stdio(false);
  139. cin.tie(0);
  140. cout.tie(0);
  141. cout.precision(10);
  142. int t=1;
  143. cin>>t;
  144. while(t--)
  145. {
  146. solve();
  147. }
  148. return 0;
  149. }

 1976D - Invertible Bracket Sequences

        题意:

        思路:我们统计序列前i个有多少个左括号是剩余的,然后思考(l , r)的选择有何特征:可以发现,若第i位之前所剩余的左括号跟第j位之前所剩余的左括号数量一样,那么(i + 1, j)这个区间就可能被选择,否则一定不会被选择。

        因此我们将剩余左括号数量相同的位置放一起,然后考虑其区间能否真的被选中。通过观察可以发现:若(i , j)之间位置的剩余左括号数量小于等于第i位之前所剩余的左括号的两倍,那么这个区间就可以被选中,因此本题转换成RMQ问题。

        光这样的复杂度是O(n^{2}logn)的,然后发现在枚举位置时,随着起始位置的增大,末尾位置也一定是非递减的,因此用双指针可以将复杂度变为O(nlogn)

        

  1. // Problem: D. Invertible Bracket Sequences
  2. // Contest: Codeforces - Educational Codeforces Round 166 (Rated for Div. 2)
  3. // URL: https://codeforces.com/contest/1976/problem/D
  4. // Memory Limit: 256 MB
  5. // Time Limit: 2000 ms
  6. //
  7. // Powered by CP Editor (https://cpeditor.org)
  8. #include <bits/stdc++.h>
  9. using namespace std;
  10. #define LL long long
  11. #define pb push_back
  12. #define x first
  13. #define y second
  14. #define endl '\n'
  15. const LL maxn = 4e05+7;
  16. const LL N = 5e05+10;
  17. #define int long long
  18. const LL mod = 1e09+7;
  19. const int inf = 0x3f3f3f3f;
  20. const LL llinf = 5e18;
  21. typedef pair<int,int>pl;
  22. priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
  23. priority_queue<LL> ma;//大根堆
  24. LL gcd(LL a, LL b){
  25. return b > 0 ? gcd(b , a % b) : a;
  26. }
  27. LL lcm(LL a , LL b){
  28. return a / gcd(a , b) * b;
  29. }
  30. int n , m;
  31. vector<int>a(N , 0);
  32. void init(int n){
  33. for(int i = 0 ; i <= n ; i ++){
  34. a[i] = 0;
  35. }
  36. }
  37. int Max[N][21];
  38. int Min[N][21];
  39. struct ST{
  40. void init(){
  41. for(int i = 1 ; i <= n ; i ++){
  42. Max[i][0] = a[i];
  43. Min[i][0] = a[i];
  44. }
  45. }
  46. void work(){
  47. for(int j = 1;j <= 21;j++)
  48. for(int i = 1;i + (1 << j) - 1 <= n ; i++){
  49. Max[i][j] = max(Max[i][j - 1] , Max[i + (1 << (j - 1))][j - 1]);
  50. Min[i][j] = min(Min[i][j - 1] , Min[i + (1 << (j - 1))][j - 1]);
  51. }
  52. }
  53. int QueryMax(int l,int r)
  54. {
  55. int k = log2(r-l+1);
  56. return max(Max[l][k],Max[r-(1<<k)+1][k]);//把拆出来的区间分别取最值
  57. }
  58. int QueryMin(int l , int r){
  59. int k = log2(r-l+1);
  60. return min(Min[l][k],Min[r-(1<<k)+1][k]);//把拆出来的区间分别取最值
  61. }
  62. };
  63. void solve()
  64. {
  65. //左括号等于右括号且
  66. string s;
  67. cin >> s;
  68. s = "0" + s;
  69. int len = s.size();
  70. n = len + 5;
  71. a[0] = 0;
  72. vector<int>st[len];
  73. for(int i = 1 ; i < len ; i++){
  74. if(s[i] == '('){
  75. a[i] = a[i - 1] + 1;
  76. }
  77. else{
  78. a[i] = a[i - 1] - 1;
  79. }
  80. st[a[i]].pb(i);
  81. }
  82. //RMQ
  83. ST stb;
  84. stb.init();
  85. stb.work();
  86. int cnt = 0;
  87. for(int i = 1 ; i < len ; i ++){
  88. if(st[i].size() <= 1)
  89. continue;
  90. int len = st[i].size();
  91. int r = 0;
  92. for(int l = 0 ; l < len ; l ++){
  93. if(r == len){
  94. cnt += (r - l - 1);
  95. continue;
  96. }
  97. int left = st[i][l] , right = st[i][r];
  98. while(r < len && stb.QueryMax(left , right) <= i * 2){
  99. r++;
  100. if(r == len){
  101. break;
  102. }
  103. right = st[i][r];
  104. }
  105. cnt += (r - l - 1);
  106. }
  107. }
  108. cout << cnt << endl;
  109. }
  110. signed main()
  111. {
  112. ios::sync_with_stdio(false);
  113. cin.tie(0);
  114. cout.tie(0);
  115. cout.precision(10);
  116. int t=1;
  117. cin>>t;
  118. while(t--)
  119. {
  120. solve();
  121. }
  122. return 0;
  123. }

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

闽ICP备14008679号