题目链接

A - Streets of Working Lanterns - 2

首先将每一个括号匹配串进行一次缩减,即串内能匹配掉的就匹配掉,每个串会变成连续的$y$个右括号+连续$z$个左括号。

我们把缩减后的串分成四类:

第一类:只有左括号

第二类:左右括号都有,且$z$大于等于$y$

第三类:左右括号都有,且$z$小于$y$

第四类:只有右括号

类与类之间肯定是按第$1$,$2$,$3$,$4$类的顺序放置。

第一类内部和第四类内部可以随便放。第二类的放置顺序也很容易想。

问题出在第三类放置的顺序,按照$z$大的先放是正确方式,其余都能举出反例。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxn = 2e5 + 10;
  5.  
  6. struct X {
  7. int y, z;
  8. int id, tp;
  9. }s[maxn];
  10. int n;
  11. char t[maxn];
  12.  
  13. bool cmp(const X& a, const X& b) {
  14. if(a.tp != b.tp) return a.tp < b.tp;
  15. if(a.tp == 2) {
  16. if(a.y != b.y) return a.y < b.y;
  17. return a.z > b.z;
  18. } else if(a.tp == 3) {
  19. return a.z > b.z;
  20. } else {
  21. return 0;
  22. }
  23. }
  24.  
  25. int main() {
  26. scanf("%d", &n);
  27. for(int i = 0; i < n; i ++) {
  28. scanf("%s", t);
  29. int z = 0, y = 0;
  30. for(int j = 0; t[j]; j ++) {
  31. if(t[j] == '(') z ++;
  32. else {
  33. if(z) z --;
  34. else y ++;
  35. }
  36. }
  37. s[i].y = y;
  38. s[i].z = z;
  39. s[i].id = i;
  40. /* ))) y个 ((( z个 */
  41. if(y + z == 0) s[i].tp = 0;
  42. else if(y == 0 && z != 0) s[i].tp = 1;
  43. else if(y != 0 && z == 0) s[i].tp = 4;
  44. else if(z - y >= 0) s[i].tp = 2;
  45. else s[i].tp = 3;
  46. }
  47. sort(s, s + n, cmp);
  48. int sum = 0;
  49. int fail = 0;
  50. for(int i = 0; i < n; i ++) {
  51. sum = sum - s[i].y;
  52. if(sum < 0) {
  53. fail = 1;
  54. break;
  55. }
  56. sum = sum + s[i].z;
  57. }
  58. if(fail || sum != 0) {
  59. printf("NO\n");
  60. } else {
  61. printf("YES\n");
  62. for(int i = 0; i < n; i ++) {
  63. printf("%d", s[i].id + 1);
  64. if(i < n - 1) printf(" ");
  65. else printf("\n");
  66. }
  67. }
  68. return 0;
  69. }
  70.  
  71. /*
  72. 4
  73. (((((
  74. )))))((
  75. ))(
  76. )
  77.  
  78. y大的先放会无解
  79. 4
  80. (((((
  81. ))))(
  82. )))((
  83. )
  84.  
  85. */

B - Pursuing the Happiness

先找出有多少个区间是happiness,接下里分情况讨论:

如果没有:要注意交换后可能出现happiness。

如果有$1$个:那么可以有多少方式,例如交换第一个和第二个。

如果有$2$个:可以有多种方式,例如第一个区间的第一个字母和第二个区间的第二个字母交换。

如果大于等于$3$个:无解。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int N = 4e5 + 10;
  5. char S[N], T[N] = "happiness";
  6. int nx[N];
  7. int slen, tlen;
  8. vector<int > pos;
  9.  
  10. void getNext()
  11. {
  12. int j, k;
  13. j = 0; k = -1; nx[0] = -1;
  14. while(j < tlen)
  15. if(k == -1 || T[j] == T[k])
  16. nx[++j] = ++k;
  17. else
  18. k = nx[k];
  19. }
  20.  
  21. int KMP_Count()
  22. {
  23. int ans = 0;
  24. int i, j = 0;
  25.  
  26. if(slen == 1 && tlen == 1)
  27. {
  28. if(S[0] == T[0])
  29. return 1;
  30. else
  31. return 0;
  32. }
  33. getNext();
  34. for(i = 0; i < slen; i++)
  35. {
  36. while(j > 0 && S[i] != T[j])
  37. j = nx[j];
  38. if(S[i] == T[j])
  39. j++;
  40. if(j == tlen)
  41. {
  42. ans++;
  43. pos.push_back(i);
  44. j = nx[j];
  45. }
  46. }
  47. return ans;
  48. }
  49.  
  50. int main() {
  51. srand(time(NULL));
  52. scanf("%s", S);
  53. slen = strlen(S);
  54. tlen = strlen(T);
  55. KMP_Count();
  56. if(slen < 9) {
  57. printf("YES\n");
  58. printf("1 2\n");
  59. return 0;
  60. }
  61. if(pos.size() == 0) {
  62. printf("YES\n");
  63. int x, y;
  64. while(1) {
  65. x = rand() % slen;
  66. y = rand() % slen;
  67. if(x == y) continue;
  68. swap(S[x], S[y]);
  69. pos.clear();
  70. KMP_Count();
  71. if(pos.size() == 0) break;
  72. swap(S[x], S[y]);
  73. }
  74. printf("%d %d\n", x + 1, y + 1);
  75. } else if(pos.size() == 1) {
  76. // [pos[0] - 8 ,pos[0]]
  77. printf("YES\n");
  78. int x = 0, y = 1;
  79. printf("%d %d\n", x + pos[0] - 8 + 1, y + pos[0] - 8 + 1);
  80. } else if(pos.size() == 2) {
  81. int x = 0, y = 1;
  82. printf("YES\n");
  83. printf("%d %d\n", x + pos[0] - 8 + 1, y + pos[1] - 8 + 1);
  84. } else {
  85. printf("NO\n");
  86. }
  87. return 0;
  88. }

C - Urn with Balls

留。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<string.h>
  4. using namespace std;
  5. int main()
  6. {
  7. long long a,b,c,n,m;
  8. while(~scanf("%lld%lld%lld",&a,&b,&c))
  9. {
  10. scanf("%lld%lld",&n,&m);
  11. long long t1,t2;
  12. if(a+c<=n&&b<=m)t1=a+b+c;
  13. else if(n>=m)
  14. {
  15. if(a+c<=n&&b>m)
  16. t1=m;
  17. else if(a+c>n&&b>m)
  18. t1=m;
  19. else if(a+c>n&&b<=m)
  20. t1=n;
  21. }
  22. else
  23. {
  24. if(a+c<=n&&b>m)
  25. t1=m;
  26. else if(a+c>n&&b>m)
  27. t1=n;
  28. else if(a+c>n&&b<=m)
  29. t1=n;
  30. }
  31. if(a<=n&&b+c<=m)t2=a+b+c;
  32. else if(n>=m)
  33. {
  34. if(a<=n&&b+c>m)t2=m;
  35. else if(a>n&&b+c>m)t2=m;
  36. else if(a>n&&b+c<=m)t2=n;
  37. }
  38. else
  39. {
  40. if(a<=n&&b+c>m)t2=m;
  41. else if(a>n&&b+c>m)t2=n;
  42. else if(a>n&&b+c<=m)t2=n;
  43. }
  44. printf("%lld\n",min(t1,t2));
  45. }
  46. return 0;
  47. }

D - Jumps

如果所有的数字的$gcd$是$x$的约数,则可行,否则不可行。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxn = 2e5 + 10;
  5. int n, x;
  6.  
  7. int gcd(int a, int b) {
  8. if(b == 0) return a;
  9. return gcd(b, a % b);
  10. }
  11.  
  12. int main() {
  13. scanf("%d%d", &n, &x);
  14. int g;
  15. for(int i = 1; i <= n; i ++) {
  16. int y;
  17. scanf("%d", &y);
  18. if(i == 1) g = y;
  19. else g = gcd(g, y);
  20. }
  21. if(abs(x) % g) printf("NO\n");
  22. else printf("YES\n");
  23. return 0;
  24. }

E - Bonuses and Teleports

宝石和跳跃机合起来排序,最左边跳跃机左边那些宝石必须来回走一次,最右边跳跃机右边的那些宝石必须来回走一次。

然后计算每相邻两个跳跃机之间的宝石怎么取费用最小,枚举一下哪个从宝石断开就可以了。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxn = 4e5 + 10;
  5. struct X {
  6. int tp;
  7. long long x;
  8. }s[maxn];
  9. int n, m;
  10.  
  11. bool cmp(const X& a, const X& b) {
  12. if(a.x != b.x) return a.x < b.x;
  13. return a.tp > b.tp;
  14. }
  15.  
  16. long long work(int L, int R) {
  17. // cout << L << " - " << R << endl;
  18. if(R - L < 2) return 0LL;
  19. long long res = s[R].x - s[L].x;
  20. for(int i = L; i <= R - 1; i ++) {
  21. long long sum = (s[i].x - s[L].x) * 2LL;
  22. sum += (s[R].x - s[i + 1].x) * 2LL;
  23. res = min(res, sum);
  24. }
  25. return res;
  26. }
  27.  
  28. int main() {
  29. scanf("%d%d", &n, &m);
  30. for(int i = 0; i < n; i ++) {
  31. scanf("%lld", &s[i].x);
  32. s[i].tp = 0;
  33. }
  34. for(int i = n; i < n + m; i ++) {
  35. scanf("%lld", &s[i].x);
  36. s[i].tp = 1;
  37. }
  38. // cout << "debug" << endl;
  39. sort(s, s + n + m, cmp);
  40. int pre = -1;
  41. for(int i = 0; i < n + m; i ++) {
  42. if(s[i].tp == 0) {
  43. pre = i;
  44. break;
  45. }
  46. }
  47. long long ans = 0;
  48. ans = abs(s[pre].x - s[0].x) * 2LL;
  49.  
  50. while(1) {
  51. int now = -1;
  52. for(int i = pre + 1; i < n + m; i ++) {
  53. if(s[i].tp == 0) {
  54. now = i;
  55. break;
  56. }
  57. }
  58. if(now == -1) {
  59. ans = ans + abs(s[n + m - 1].x - s[pre].x) * 2LL;
  60. break;
  61. }
  62. // [pre, now]
  63. ans = ans + work(pre, now);
  64. pre = now;
  65. }
  66. printf("%lld\n", ans);
  67. return 0;
  68. }

F - Circuits

这是我做的第一个交互题。我是随机做法,交了很多次,有一次是通过的,其余全是答案错误。

具体想法是这样的:

假设我们知道其中一个可用的是哪个,那么我们就可以找出所有可用的。

然后我就去猜哪个是可用的,然后验证看看是不是满足条件。验证的时候就是看不可用的数量是否严格小于一半。

因为题目要求在$4n$次出解,因此我们至少可以猜$4$次,中一次就可以了,而且每次猜对的概率约等于$1/2$,再加一点剪枝,可以使得猜的次数增加,具体可以看代码。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxn = 100010;
  5. int n;
  6. vector<int> ans;
  7. int f[maxn];
  8. char s1[maxn], s2[maxn];
  9.  
  10. int main() {
  11. srand(time(NULL));
  12. scanf("%d", &n);
  13. int h = (n - 1) / 2;
  14. for(int t = 0; t < n; t ++) {
  15. ans.clear();
  16. int x;
  17. int y = rand() % (n - t) + 1;
  18. int num = 0;
  19. for(int i = 1; i <= n; i ++) {
  20. if(f[i]) continue;
  21. num ++;
  22. if(num == y) {
  23. x = i;
  24. break;
  25. }
  26. }
  27. f[x] = 1;
  28. int fail = 0;
  29. for(int i = 1; i <= n; i ++) {
  30. if(i == x) {
  31. ans.push_back(i);
  32. continue;
  33. }
  34. printf("? %d %d\n", x, i);
  35. fflush(stdout);
  36. scanf("%s%s", s1, s2);
  37. if(s1[0] == '+' && s2[0] == '+') {
  38. ans.push_back(i);
  39. }
  40. if(i - ans.size() > h) {
  41. fail = 1;
  42. break;
  43. }
  44. }
  45. if(n - ans.size() > h) fail = 1;
  46. if(fail == 0) break;
  47. }
  48. printf("! %d", ans.size());
  49. sort(ans.begin(), ans.end());
  50. for(int i = 0; i < ans.size(); i ++) {
  51. printf(" %d", ans[i]);
  52. }
  53. printf("\n");
  54. fflush(stdout);
  55. return 0;
  56. }

G - I love Codeforces

模拟一下就可以了。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxn = 2e5 + 10;
  5. string name[maxn];
  6. int n, m;
  7.  
  8. int p[maxn], q[maxn];
  9.  
  10. int main() {
  11. scanf("%d", &n);
  12. for(int i = 1; i <= n; i ++) {
  13. cin >> name[i];
  14. q[i] = i;
  15. }
  16. int m;
  17. scanf("%d", &m);
  18. int x, y;
  19. for(int i = 1; i <= m; i ++) {
  20.  
  21. scanf("%d%d", &x, &y);
  22. p[x] = p[y] + 1;
  23. q[x] = q[y];
  24. }
  25. while(p[1]) {
  26. printf("I_love_");
  27. p[1] --;
  28. }
  29. cout << name[q[1]] << endl;
  30. return 0;
  31. }

H - Perfect Ban

找到一个最大值的位置,最大值的位置一定要被删掉,不然留下个最值不会让答案更优,接下来有三种策略:

第一种:删掉最大值所在行和列。

第二种:删掉最大值所在的行,再删除剩余矩阵最大值所在的列。

第三种:删掉最大值所在的列,再删除剩余矩阵最大值所在的行。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxn = 1010;
  5. int n, m;
  6. int a[maxn][maxn];
  7. vector<int> mx;
  8. vector<int> r;
  9. vector<int> c;
  10.  
  11. int work(int x, int y) {
  12. int res = 0;
  13. for(int i = 1; i <= n; i ++) {
  14. for(int j = 1; j <= m; j ++) {
  15. if(i == x || j == y) continue;
  16. res = max(res, a[i][j]);
  17. }
  18. }
  19. return res;
  20. }
  21.  
  22. int main() {
  23. scanf("%d%d", &n, &m);
  24. int mr = 1, mc = 1, Max = a[1][1];
  25. for(int i = 1; i <= n; i ++) {
  26. for(int j = 1; j <= m; j ++) {
  27. scanf("%d", &a[i][j]);
  28. if(a[i][j] > Max) {
  29. Max = a[i][j];
  30. mr = i;
  31. mc = j;
  32. }
  33. }
  34. }
  35.  
  36. for(int i = 0; i < 3; i ++) {
  37. mx.push_back(0);
  38. r.push_back(0);
  39. c.push_back(0);
  40. }
  41.  
  42. // 删最大值所在行列
  43. r[0] = mr;
  44. c[0] = mc;
  45. mx[0] = work(mr, mc);
  46.  
  47. r[1] = mr;
  48. // 先删最大值所在行,再删最大值所在列
  49. int kk = work(mr, 0);
  50. for(int i = 1; i <= n; i ++) {
  51. if(i == mr) continue;
  52. for(int j = 1; j <= m; j ++) {
  53. if(a[i][j] == kk) {
  54. c[1] = j;
  55. }
  56. }
  57. }
  58. mx[1] = work(r[1], c[1]);
  59.  
  60. c[2] = mc;
  61. // 先删最大值所在列,再删最大值所在行
  62. int qq = work(0, mc);
  63. for(int i = 1; i <= n; i ++) {
  64. for(int j = 1; j <= m; j ++) {
  65. if(j == mc) continue;
  66. if(a[i][j] == qq) {
  67. r[2] = i;
  68. }
  69. }
  70. }
  71. mx[2] = work(r[2], c[2]);
  72.  
  73. int ans = 1e9 + 7;
  74. int idx = 0;
  75. for(int i = 0; i < 3; i ++) {
  76. if(mx[i] < ans) {
  77. ans = mx[i];
  78. idx = i;
  79. }
  80. }
  81.  
  82. printf("%d %d\n", r[idx], c[idx]);
  83.  
  84. return 0;
  85. }

I - Matrix God

一开始的做法:检查每一行的和是否相同,每一列的和是否相同,然后随机选择$n$个点看是否相同,但是一直答案错误。后来意识到一个问题,假设数据是$1000*1000$的矩阵,$C$矩阵和$A*B$矩阵的差别仅仅是其中的一个$2*2$子矩阵,这时候,可以构造出数据使得每一行每一列的和都相同,随机选择$n$个点大概率也是相同的,所以检测不出来。

后来我检测了每一行的$hash$值,即和字符串$hash$做法一样,每一行当做一个字符串,$A*B$矩阵每一行的hash值是可以$O(n^2)$得到的,这样就AC了。

看到大佬都是随机构造一个$1*n$的$X$矩阵做的,只要检查$X*A*B$是否等于$X*C$即可,膜。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. long long mod = 1e9 + 7;
  5. const int maxn = 1100;
  6. long long a[3][maxn][maxn];
  7. long long r[3][maxn][maxn];
  8. long long base = 131LL;
  9. int n;
  10.  
  11. int main() {
  12. scanf("%d", &n);
  13. for(int t = 0; t < 3; t ++) {
  14. for(int i = 1; i <= n; i ++) {
  15. for(int j = 1; j <= n; j ++) {
  16. scanf("%lld", &a[t][i][j]);
  17. r[t][i][j] = (r[t][i][j - 1] * base % mod + a[t][i][j]) % mod;
  18. }
  19. }
  20. }
  21. int fail = 0;
  22.  
  23. // 检查每一行的 hash 值
  24. for(int i = 1; i <= n; i ++) {
  25. long long A = 0;
  26. for(int k = 1; k <= n; k ++) {
  27. long long B = a[0][i][k] * r[1][k][n] % mod;
  28. A = (A + B) % mod;
  29. }
  30. if(A != r[2][i][n]) fail = 1;
  31. }
  32.  
  33. if(fail) printf("NO\n");
  34. else printf("YES\n");
  35. return 0;
  36. }

J - Catch the Monster

还在做。

K - Competitions

区间按右端点排序,然后就可以$dp$了,中间要二分一个位置$p$,只有位置$[1,p]$是可以转移到位置$i$的状态的。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxn = 2e5 + 10;
  5. struct X {
  6. int id;
  7. int L, R;
  8. long long c;
  9. }s[maxn];
  10. int n;
  11.  
  12. int pre[maxn];
  13. int wei[maxn];
  14. long long fen[maxn];
  15. long long tim[maxn];
  16.  
  17. vector<int> use;
  18.  
  19. bool cmp(const X &a, const X &b) {
  20. return a.R < b.R;
  21. }
  22.  
  23. void up(long long x, long long y, int idx) {
  24. if(x > fen[idx - 1] || (x == fen[idx - 1] && y < tim[idx - 1])) {
  25. fen[idx] = x;
  26. tim[idx] = y;
  27. wei[idx] = idx;
  28. } else {
  29. fen[idx] = fen[idx - 1];
  30. tim[idx] = tim[idx - 1];
  31. wei[idx] = wei[idx - 1];
  32. }
  33. }
  34.  
  35. int main() {
  36. scanf("%d", &n);
  37. for(int i = 1; i <= n; i ++) {
  38. pre[i] = -1;
  39. scanf("%d%d%lld", &s[i].L, &s[i].R, &s[i].c);
  40. s[i].id = i;
  41. }
  42. sort(s + 1, s + 1 + n, cmp);
  43. for(int i = 1; i <= n; i ++) {
  44. int L = 1, R = i - 1, pos = -1;
  45. while(L <= R) {
  46. int mid = (L + R) / 2;
  47. if(s[mid].R > s[i].L) R = mid - 1;
  48. else pos = mid, L = mid + 1;
  49. }
  50. if(pos == -1) {
  51. long long now_fen = s[i].c;
  52. long long now_tim = s[i].R - s[i].L;
  53. if(i == 1) {
  54. wei[i] = 1;
  55. fen[i] = now_fen;
  56. tim[i] = now_tim;
  57. } else {
  58. up(now_fen, now_tim, i);
  59. }
  60. } else {
  61. long long now_fen = s[i].c + fen[pos];
  62. long long now_tim = s[i].R - s[i].L + tim[pos];
  63. pre[i] = wei[pos];
  64. up(now_fen, now_tim, i);
  65. }
  66. }
  67.  
  68. long long ans_fen = 0;
  69. long long ans_tim = 0;
  70. for(int i = 1; i <= n; i ++) {
  71. if(fen[i] > ans_fen) {
  72. ans_fen = fen[i];
  73. ans_tim = tim[i];
  74. } else if(fen[i] == ans_fen) {
  75. ans_tim = min(ans_tim, tim[i]);
  76. }
  77. }
  78.  
  79. int last = -1;
  80. for(int i = 1; i <= n; i ++) {
  81. if(fen[i] == ans_fen && tim[i] == ans_tim) {
  82. last = i;
  83. break;
  84. }
  85. }
  86.  
  87. while(last != -1) {
  88. use.push_back(last);
  89. last = pre[last];
  90. }
  91.  
  92. for(int i = 0; i < use.size(); i ++) {
  93. use[i] = s[use[i]].id;
  94. }
  95. sort(use.begin(), use.end());
  96.  
  97. printf("%d %lld %lld\n", use.size(), ans_fen, ans_tim);
  98. for(int i = 0; i < use.size(); i ++) {
  99. printf("%d", use[i]);
  100. if(i < use.size() - 1) printf(" ");
  101. else printf("\n");
  102. }
  103. return 0;
  104. }

L - High Probability Cast

区间按$L$排序,$L$相同的只保留$R$最大的那个。

然后一个一个区间加入,加入第$i$个区间的时候,比$Li$小的那些位置不需要考虑了,概率肯定是100%。

只需考虑比$Li$大的那些位置,画画图可以发现是在维护一个斜率递减的图形。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const double height = 2e9;
  5. const double eps = 1e-8;
  6. const int maxn = 2e5 + 10;
  7. struct X {
  8. double L, R;
  9. double nowL, nowR;
  10. int id;
  11. }s[maxn];
  12. stack<int> st;
  13. vector<int> vec;
  14. int n;
  15.  
  16. bool cmp(const X& a, const X& b) {
  17. if(fabs(a.L - b.L) < eps) return a.R > b.R;
  18. return a.L < b.L;
  19. }
  20.  
  21. double work(double x, int id) {
  22. return (s[id].R - x) * height / (s[id].R - s[id].L);
  23. }
  24.  
  25. int main() {
  26. scanf("%d", &n);
  27. for(int i = 0; i < n; i ++) {
  28. scanf("%lf%lf", &s[i].L, &s[i].R);
  29. s[i].nowL = s[i].L;
  30. s[i].nowR = s[i].R;
  31. s[i].id = i + 1;
  32. }
  33. sort(s, s + n, cmp);
  34. for(int i = 0; i < n; i ++) {
  35. if(st.empty()) {
  36. st.push(i);
  37. continue;
  38. }
  39. if(fabs(s[i].L - s[i - 1].L) < eps) {
  40. continue;
  41. }
  42. while(!st.empty()) {
  43. int id = st.top();
  44. double xL = max(s[id].nowL, s[i].nowL);
  45. double xR = min(s[id].nowR, s[i].nowR);
  46. if(xR < xL) {
  47. st.pop();
  48. continue;
  49. }
  50. if(work(xL, id) <= work(xL, i) + eps
  51. && work(xR, id) <= work(xR, i) + eps) {
  52. st.pop();
  53. } else {
  54. double left = xL, right = xR, pos;
  55. int limit = 50;
  56. while(limit --) {
  57. pos = (left + right) / 2;
  58. if(work(pos, id) < work(pos, i)) left = pos;
  59. else right = pos;
  60. }
  61. s[i].nowR = pos;
  62. s[id].nowL = pos;
  63. break;
  64. }
  65. }
  66. st.push(i);
  67. }
  68. while(!st.empty()) {
  69. vec.push_back(st.top());
  70. st.pop();
  71. }
  72.  
  73. int Q;
  74. scanf("%d", &Q);
  75. while(Q --) {
  76. double x;
  77. scanf("%lf", &x);
  78. if(x <= s[vec[0]].nowL + eps) {
  79. printf("%d\n", s[vec[0]].id);
  80. continue;
  81. }
  82. int left = 0, right = vec.size() - 1, ans = -1;
  83. while(left <= right) {
  84. int mid = (left + right) / 2;
  85. if(x < s[vec[mid]].nowL) right = mid - 1;
  86. else ans = mid, left = mid + 1;
  87. }
  88. if(ans == -1) ans = 0;
  89. printf("%d\n", s[vec[ans]].id);
  90. }
  91.  
  92. return 0;
  93. }

M - Last Man Standing

每次让一个$a_i$为$0$的分配给一个$a_j$不为$0$的人,然后$a_j$就可以减去$1$,一直这样操作。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxn = 200000 + 10;
  5. int n;
  6. int a[maxn];
  7. queue<int> q;
  8. int ans[maxn];
  9.  
  10. int main() {
  11. scanf("%d", &n);
  12. int now = -1;
  13. for(int i = 1; i <= n; i ++) {
  14. scanf("%d", &a[i]);
  15. if(a[i]) now = i;
  16. if(a[i] == 0) q.push(i);
  17. }
  18. if(now == -1) {
  19. printf("YES\n");
  20. return 0;
  21. }
  22. int fail = 0;
  23. while(now) {
  24. if(q.empty()) {
  25. fail = 1;
  26. break;
  27. }
  28. int f = q.front();
  29. q.pop();
  30. ans[f] = now;
  31. a[now] --;
  32. if(a[now] == 0) {
  33. q.push(now);
  34. now --;
  35. }
  36. }
  37. for(int i = 1; i <= n; i ++) {
  38. if(a[i]) fail = 1;
  39. }
  40. if(fail) printf("NO\n");
  41. else {
  42. printf("YES\n");
  43. for(int i = n; i > 1; i --) {
  44. if(ans[i])
  45. printf("%d %d\n", ans[i], i);
  46. }
  47. }
  48. return 0;
  49. }

2017, X Samara Regional Intercollegiate Programming Contest 题解的更多相关文章

  1. 2017, X Samara Regional Intercollegiate Programming Contest E. Bonuses and Teleports (思维,模拟)

    题意:在\(x\)轴上有很多传送点和钻石,当位于传送点上时,可以传送到其他任意传送点(不记操作数),位于钻石上时可以吃掉它,每次可以移动一个单位,问最少多少次可以吃掉所有的钻石. 题解:对于某个位置上 ...

  2. 2017, X Samara Regional Intercollegiate Programming Contest B.Pursuing the Happiness (string函数)

    题意:给你一个字符串,可以交换两个字符的位置,问操作后能否在字符串中找到子串\("happiness"\),如果不能,输出交换的两个位置. 题解:这题其实用string中的find ...

  3. 2017, X Samara Regional Intercollegiate Programming Contest M. Last Man Standing (贪心,双指针)

    题意:有\(n\)个吃鸡玩家,在某个时间段给你他们每个人的杀敌数,判断数据是否合法,并输出每个人对应的杀敌情况. 题解:刚开始写的是直接暴力枚举,向后去找并且标记,然后存到vector最后输出,结果一 ...

  4. Gym100971B Gym100971C Gym100971F Gym100971G Gym100971K Gym100971L(都是好写的题。。。) IX Samara Regional Intercollegiate Programming Contest Russia, Samara, March 13, 2016

    昨天训练打的Gym,今天写题解. Gym100971B 这个题就是输出的时候有点小问题,其他的都很简单. 总之,emnnn,简单题. 代码: #include<iostream> #inc ...

  5. IX Samara Regional Intercollegiate Programming Contest F 三分

    F. Two Points time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  6. Codeforces Gym100971 B.Derangement (IX Samara Regional Intercollegiate Programming Contest Russia, Samara, March 13)

    昨天训练打的Gym,今天写题解. 这个题就是输出的时候有点小问题,其他的都很简单. 代码: #include<iostream> #include<cstring> #incl ...

  7. X Samara Regional Intercollegiate Programming Contest DIV2

    http://codeforces.com/gym/101341 其实我觉得这份题很不错的,虽然是div2,但是感觉对我挺有帮助(我比较垃圾0.0),还没补完(做的时候一直蒙逼,要补很多题)先写一点点 ...

  8. Codeforces Gym100971 L.Chess Match (IX Samara Regional Intercollegiate Programming Contest Russia, Samara, March 13)

    这个题就是两个队,看最多能赢的个数,然后比较一下,看两个队是都能赢彼此,还是只有一个队赢的可能性最大.表达能力不好,意思差不多... 和田忌赛马有点像,emnnn,嗯. 代码: 1 #include& ...

  9. Codeforces Gym100971 K.Palindromization-回文串 (IX Samara Regional Intercollegiate Programming Contest Russia, Samara, March 13)

    这个题就是从字符串中删除一个字符,然后剩下的是回文串. 我写的代码虽然长得好看,但是循环里面的比较条件容易想错,太智障了... 一开始写的是计数比较,但是有的时候下标相同的也比较了,为了简单一些,直接 ...

随机推荐

  1. SoapUI使用笔记备忘

    1.安装好SoapUI后,新建一个REST项目 注意新建REST项目时,需要输入测试站点的地址,即IP+端口 之后点击OK就建立好了项目,但是新项目会默认自带一个根路径访问请求,可以删除(一般没用) ...

  2. AIO 开始不定时的抛异常: java.io.IOException: 指定的网络名不再可用

    一天里会抛出几个这样的错误,但发现服务还在正常的运行. java.io.IOException: 指定的网络名不再可用. at sun.nio.ch.Iocp.translateErrorToIOEx ...

  3. 线段树区间更新 lazy

    1. hdu1698 http://acm.hdu.edu.cn/showproblem.php?pid=1698 /* x y k x~y的值变为k */ #include <cstdio&g ...

  4. Java基本语法---个人参考资料

    Java语言基础组成:关键字.标识符.注释.常量和变量.运算符.语句.函数.数组 一.标识符 标识符是在程序中自定义的一些名称,由大小写字母[a-zA-Z],数字[0-9],下划线[ _ ],特殊字符 ...

  5. NodeJS 笔记 URL模块

    url模块 ,包含分析和解析 URL 的工具. var url = require('url'); url.parse(urlStr[, parseQueryString][, slashesDeno ...

  6. Java基础-SSM之Spring的AOP编程

    Java基础-SSM之Spring的AOP编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   Spring的本质说白了就是动态代理,接下来我们会体验AOP的用法.它是对OOP的 ...

  7. vue-router基本概念及使用

    index.html: <!DOCTYPE html> <html> <head> <title></title> <meta cha ...

  8. Spark记录-Scala函数与闭包

    函数声明 Scala函数声明具有以下形式 - def functionName ([list of parameters]) : [return type] Scala 如果不使用等号和方法体,则隐式 ...

  9. 关于如何在Python中使用静态、类或抽象方法的权威指南

    Python中方法的工作方式 方法是存储在类属性中的函数,你可以用下面这种方式声明和访问一个函数 >>> class Pizza(object): ... def __init__( ...

  10. Oracle 修改用户名

    1.开始- 运行 - 输入“CMD” 确定 2.在弹出来的窗口中,输入:SQLPLUS / AS SYSDBA  回车 3.然后,用命令修改:alter user 用户名 identified by ...