[关闭]
@dxbdly 2020-12-20T06:42:02.000000Z 字数 2977 阅读 173

C2020 2020.12.12模拟赛

信息学——模拟赛


1. 考试情况

当天去打THUPC2021初赛了,没打模拟赛,赛后补的题。

T1 Lights

分析

一眼显然是个搜索,考虑对于当前每个点将对应点的灯打个标记,然后往四方拓展看一眼标记就好了。

但是发现一个问题。

比如样例:

  1. 3 6
  2. 1 1 1 2
  3. 2 1 2 2
  4. 1 1 1 3
  5. 2 3 3 1
  6. 1 3 1 2
  7. 1 3 2 1

我们会发现程序并不会将这个点加入队列,为什么?

我们发现应该由拓展而来,但是这个点的灯是用 打开的,而之后被搜到。

所以存在的问题就是有可能后面会有开灯的点漏加入队列中。

那么很简单,当我们开灯的时候,判断一下要开的那盏灯的四方有没有被走到,就能将这个点加入到队列中了。

可以发现只有这两种加入队列的方式(至于证明……大致可以想成所有点都可以被分在这两类中)。

  1. //The code is from dawn_sdy
  2. #include<bits/stdc++.h>
  3. #define pi pair<int, int>
  4. #define mp make_pair
  5. #define pb push_back
  6. using namespace std;
  7. inline int read() {
  8. int x = 0;
  9. char c = getchar();
  10. bool f = 0;
  11. while(!isdigit(c)) f |= (c == '-'), c = getchar();
  12. while(isdigit(c)) x = (x * 10) + (c ^ 48), c = getchar();
  13. return f ? -x : x;
  14. }
  15. const int maxn = 105;
  16. int n, m;
  17. vector < pi > vec[maxn][maxn];
  18. namespace Work {
  19. queue < pi > q; pi u, v;
  20. int vst[maxn][maxn], light[maxn][maxn], go[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, ans;
  21. #define fi first
  22. #define se second
  23. inline void Change1() {
  24. int sz = vec[u.fi][u.se].size();
  25. for(register int i = 0; i < sz; ++i) {
  26. v = vec[u.fi][u.se][i];
  27. if(vst[v.fi][v.se] || light[v.fi][v.se]) continue;
  28. light[v.fi][v.se] = 1, ans++;
  29. for(register int j = 0; j < 4; ++j) {
  30. int nx = v.fi + go[j][0], ny = v.se + go[j][1];
  31. if(nx < 0 || ny < 0 || nx > n || ny > n || !vst[nx][ny]) continue;
  32. q.push(v), vst[v.fi][v.se] = 1; break;
  33. }
  34. }
  35. }
  36. inline void Change2() {
  37. for(register int i = 0; i < 4; ++i) {
  38. int nx = u.fi + go[i][0], ny = u.se + go[i][1];
  39. if(nx < 0 || ny < 0 || nx > n || ny > n || vst[nx][ny] || !light[nx][ny]) continue;
  40. q.push(mp(nx, ny)), vst[nx][ny] = 1;
  41. }
  42. }
  43. inline void Search() {
  44. q.push(mp(1, 1)), vst[1][1] = light[1][1] = 1, ans = 1;
  45. while(!q.empty()) {
  46. u = q.front(); q.pop();
  47. Change1(), Change2();
  48. }
  49. printf("%d", ans);
  50. }
  51. #undef fi
  52. #undef se
  53. }
  54. int main() {
  55. n = read(), m = read();
  56. for(register int i = 1; i <= m; ++i) {
  57. int sx = read(), sy = read(), ex = read(), ey = read();
  58. vec[sx][sy].pb(mp(ex, ey));
  59. }
  60. Work::Search();
  61. return 0;
  62. }

T2 Card

分析

一道田忌赛马模型题,很容易想到一个贪心策略:

  1. 如果当前牌能够被赢下,就用最小能赢下的牌赢下
  2. 如果当前牌不能被赢下,就用所有中最小的牌对掉

由于要动态删除,直接用维护即可。

  1. //The code is from dawn_sdy
  2. #include<bits/stdc++.h>
  3. #define It set<int>::iterator
  4. using namespace std;
  5. inline int read() {
  6. int x = 0;
  7. char c = getchar();
  8. bool f = 0;
  9. while(!isdigit(c)) f |= (c == '-'), c = getchar();
  10. while(isdigit(c)) x = (x * 10) + (c ^ 48), c = getchar();
  11. return f ? -x : x;
  12. }
  13. const int maxn = 5 * 1e4 + 5;
  14. int n;
  15. int a[maxn], b[maxn << 1], ans;
  16. set <int> s; It it;
  17. int main() {
  18. n = read();
  19. for(register int i = 1; i <= n; ++i) a[i] = read(), b[a[i]] = 1;
  20. for(register int i = 1; i <= n << 1; ++i)
  21. if(!b[i]) s.insert(i);
  22. for(register int i = 1; i <= n; ++i) {
  23. it = s.end(); it--;
  24. if(*it < a[i]) {
  25. s.erase(s.begin()); continue;
  26. }
  27. it = s.lower_bound(a[i]), s.erase(it), ans++;
  28. }
  29. printf("%d", ans);
  30. return 0;
  31. }

T3 Counting

分析

由于只有三种颜色,直接前缀和求即可。

  1. //The code is from dawn_sdy
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. inline int read() {
  5. int x = 0;
  6. char c = getchar();
  7. bool f = 0;
  8. while(!isdigit(c)) f |= (c == '-'), c = getchar();
  9. while(isdigit(c)) x = (x * 10) + (c ^ 48), c = getchar();
  10. return f ? -x : x;
  11. }
  12. const int maxn = 1e5 + 5;
  13. int n, q;
  14. int sum[maxn][5];
  15. inline int calc(int l, int r, int k) { return sum[r][k] - sum[l - 1][k]; }
  16. int main() {
  17. n = read(), q = read();
  18. for(register int i = 1; i <= n; ++i) {
  19. int x = read();
  20. for(register int j = 1; j <= 3; ++j) sum[i][j] = sum[i - 1][j] + (x == j ? 1 : 0);
  21. }
  22. for(register int i = 1; i <= q; ++i) {
  23. int l = read(), r = read();
  24. printf("%d %d %d\n", calc(l, r, 1), calc(l, r, 2), calc(l, r, 3));
  25. }
  26. return 0;
  27. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注