当前位置:   article > 正文

第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组_试题来源:第十四届蓝桥杯大赛软件赛决赛 cb-5

试题来源:第十四届蓝桥杯大赛软件赛决赛 cb-5

目录

试题 A: 日期统计 .本题总分:5 分

试题 B: 01 串的熵.本题总分:5 分

试题 C: 冶炼金属.本题总分:10 分

试题 D: 飞机降落.本题总分:10 分

试题 E: 接龙数列 .本题总分:15 分

试题 F: 岛屿个数 .本题总分:15 分

试题 G: 子串简写 .本题总分:20 分

试题 H: 整数删除.本题总分:20 分

试题 I: 景区导游 .本题总分:25 分

试题 J: 砍树 .本题总分:25 分


试题 A: 日期统计 .本题总分:5

 相同的日期你只需要统计一次即可,直接dfs剪枝跑就可以了 我的答案235

试题 B: 01 串的熵.本题总分:5

二分,l=1,r=23333333>>1 ,我的答案11027421

试题 C: 冶炼金属.本题总分:10 

对于最大值,可以根据整除分块定理2知道是a/b,然后取个min就是最大值,对于最小值,二分求,复杂度O(nlogn) 

然后其实知道r=a/b,那么也不难推出l是前一个块的r+1,也就是l=a/(b+1)+1 复杂度O(N)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define endl '\n'
  5. #define x first
  6. #define y second
  7. #define pd push_back
  8. const int maxn=1e4+10;
  9. int n;
  10. ll a[maxn],b[maxn];
  11. void solve()
  12. {
  13. cin>>n;
  14. ll ma=-1,mi=-1;
  15. for(int i=1;i<=n;i++)
  16. {
  17. cin>>a[i]>>b[i];
  18. ll now=a[i]/b[i];
  19. if(ma==-1||ma>now)
  20. {
  21. ma=now;
  22. }
  23. mi=max(mi,(a[i]/(b[i]+1))+1);
  24. }
  25. cout<<mi<<" "<<ma;
  26. }
  27. int main()
  28. {
  29. ios::sync_with_stdio(0);
  30. cin.tie(0);
  31. cout.tie(0);
  32. int tn=1;
  33. //cin>>tn;
  34. while(tn--)
  35. {
  36. solve();
  37. }
  38. return 0;
  39. }

试题 D: 飞机降落.本题总分:10 

贪心寄了,还是全排列暴力~~~~~

还是dfs剪枝暴力吧,t<=10,n<=10

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define endl '\n'
  5. #define x first
  6. #define y second
  7. #define pd push_back
  8. const int maxn=1e2+10;
  9. struct node
  10. {
  11. int t,d,l;
  12. } ;
  13. int n;
  14. node a[maxn];
  15. int f[maxn];
  16. int flag;
  17. void dfs(int len,int last)
  18. {
  19. if(len==n)
  20. {
  21. flag=1;
  22. return;
  23. }
  24. for(int i=1;i<=n&&!flag;i++)
  25. {
  26. if(f[i])continue;
  27. auto [t,d,l]=a[i];
  28. if(last<=t+d)
  29. {
  30. f[i]=1;
  31. dfs(len+1,max(last+l,t+l));
  32. f[i]=0;
  33. }
  34. }
  35. }
  36. void solve()
  37. {
  38. cin>>n;
  39. flag=0;
  40. for(int i=1;i<=n;i++)
  41. {
  42. cin>>a[i].t>>a[i].d>>a[i].l;
  43. f[i]=0;
  44. }
  45. dfs(0,-1);
  46. if(flag)cout<<"YES"<<endl;
  47. else cout<<"NO"<<endl;
  48. }
  49. int main()
  50. {
  51. ios::sync_with_stdio(0);
  52. cin.tie(0);
  53. cout.tie(0);
  54. int tn=1;
  55. cin>>tn;
  56. while(tn--)
  57. {
  58. solve();
  59. }
  60. return 0;
  61. }

试题 E: 接龙数列 .本题总分:15 

考虑dp, dp[i],表示以i结尾的子序列最大长度,当前数字开头为j结尾为i,那么dp[i]=max(dp[i],dp[j]+1);,最后n-最长子序列就可以了,复杂度O(N)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define endl '\n'
  5. #define x first
  6. #define y second
  7. #define pd push_back
  8. const int maxn=1e5+10;
  9. int n;
  10. int dp[10];
  11. /*
  12. 5
  13. 11 121 22 12 2023
  14. 1
  15. */
  16. void solve()
  17. {
  18. cin>>n;
  19. for(int i=1,j;i<=n;i++)
  20. {
  21. cin>>j;
  22. int f=j,d=j%10;
  23. while(f>=10)f/=10;
  24. dp[d]=max(dp[d],dp[f]+1);
  25. }
  26. int ma=1;
  27. for(int i=0;i<10;i++)
  28. {
  29. ma=max(ma,dp[i]);
  30. //cout<<dp[i]<<endl;
  31. }
  32. cout<<n-ma<<endl;
  33. }
  34. int main()
  35. {
  36. ios::sync_with_stdio(0);
  37. cin.tie(0);
  38. cout.tie(0);
  39. int tn=1;
  40. //cin>>tn;
  41. while(tn--)
  42. {
  43. solve();
  44. }
  45. return 0;
  46. }

试题 F: 岛屿个数 .本题总分:15 

 先从最外海水跑图,记录外部海水数量,岛的4周海水得有1个方向等于外部海水.否则就是环岛的子岛屿;

跑海水从8个方向染色;

然后跑周围是外部海水的岛屿,四个方向染++cnt,最后输出cnt就是答案

0(N*N)

  1. #include <bits/stdc++.h>
  2. #define int int64_t
  3. #define endl '\n'
  4. using namespace std;
  5. const int MAX = 55;
  6. const int INF = 0x3f3f3f3f3f3f3f3fll;
  7. const int MOD = 1e9 + 7;
  8. char map_[MAX][MAX]; // 地图
  9. bool track[MAX][MAX] = {false}; // 访问标记
  10. bool outsea[MAX][MAX] = {false}; // 外海标记
  11. struct XY {
  12. int x, y;
  13. } nxt[] = {
  14. {1, 0},
  15. {-1, 0},
  16. {0, 1},
  17. {0, -1},
  18. {1, 1},
  19. {-1, 1},
  20. {1, -1},
  21. {-1, -1},
  22. };
  23. void solve() {
  24. int n, m;
  25. cin >> n >> m;
  26. for (int i = 0; i < n; i++) {
  27. cin >> map_[i];
  28. }
  29. for (int i = 0; i < n; i++) {
  30. for (int j = 0; j < m; j++) {
  31. track[i][j] = false;
  32. outsea[i][j] = false;
  33. }
  34. }
  35. // 预处理外海
  36. for (int i = 0; i < n; i++) {
  37. for (int j = 0; j < m; j++) {
  38. if (map_[i][j] == '1' or track[i][j]) continue;
  39. bool yep = false;
  40. queue<XY> que, arr;
  41. track[i][j] = true;
  42. que.push({i, j});
  43. arr.push({i, j}); // 记录搜索到的所有海域
  44. while (not que.empty()) {
  45. XY pos = que.front();
  46. que.pop();
  47. // 注意:海域搜索可以往八个方向走,陆地搜索只能朝四个方向
  48. for (int i = 0; i < 8; i++) {
  49. XY nw = {pos.x + nxt[i].x, pos.y + nxt[i].y};
  50. if (0 <= nw.x and nw.x < n and 0 <= nw.y and nw.y < m) {
  51. if (map_[nw.x][nw.y] == '0' and track[nw.x][nw.y] == false) {
  52. track[nw.x][nw.y] = true;
  53. que.push(nw);
  54. arr.push(nw);
  55. }
  56. } else {
  57. yep = true; // 如果有一次搜索到地图外,标记此次搜索的所有区域为外海
  58. }
  59. }
  60. }
  61. if (yep) {
  62. while (not arr.empty()) {
  63. XY pos = arr.front();
  64. arr.pop();
  65. outsea[pos.x][pos.y] = true; // 标记搜索到的海域为外海
  66. }
  67. }
  68. }
  69. }
  70. // 别忘了清空访问标记
  71. for (int i = 0; i < n; i++) {
  72. for (int j = 0; j < m; j++) {
  73. track[i][j] = false;
  74. }
  75. }
  76. // 处理岛屿
  77. int cnt = 0;
  78. for (int i = 0; i < n; i++) {
  79. for (int j = 0; j < m; j++) {
  80. if (map_[i][j] == '0' or track[i][j]) continue;
  81. bool yep = false;
  82. queue<XY> que;
  83. track[i][j] = true;
  84. que.push({i, j});
  85. while (not que.empty()) {
  86. XY pos = que.front();
  87. que.pop();
  88. for (int i = 0; i < 4; i++) {
  89. XY nw = {pos.x + nxt[i].x, pos.y + nxt[i].y};
  90. if (0 <= nw.x and nw.x < n and 0 <= nw.y and nw.y < m) {
  91. if (map_[nw.x][nw.y] == '1') {
  92. if (track[nw.x][nw.y] == false) {
  93. track[nw.x][nw.y] = true;
  94. que.push(nw);
  95. }
  96. } else {
  97. if (outsea[nw.x][nw.y]) {
  98. yep = true; // 搜索到外海为外岛
  99. }
  100. }
  101. } else {
  102. yep = true; // 搜索到边界外为外岛
  103. }
  104. }
  105. }
  106. if (yep) {
  107. cnt++; // 外岛计数
  108. }
  109. }
  110. }
  111. cout << cnt << endl;
  112. }
  113. int32_t main() {
  114. cin.tie(0);
  115. cout.tie(0);
  116. ios::sync_with_stdio(0);
  117. int t;
  118. cin >> t;
  119. while (t--)
  120. solve();
  121. return 0;
  122. }

试题 G: 子串简写 .本题总分:20 

把c1的位置存起来,对于每个c2位置二分找最小符合的位置,ans加上这个位置下标就可以了

也可以双指针暴力

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define endl '\n'
  5. #define x first
  6. #define y second
  7. #define pd push_back
  8. #define pii pair<int,int>
  9. const int maxn=5e5+10;
  10. int n,k;
  11. char s[maxn],a,b;
  12. /*
  13. 4
  14. abababdb a b
  15. 4
  16. ba a b
  17. */
  18. void solve()
  19. {
  20. cin>>k;
  21. cin>>s+1;
  22. cin>>a>>b;
  23. n=strlen(s+1);
  24. vector<int>va,vb;
  25. for(int i=1;i<=n;i++)
  26. {
  27. if(s[i]==a)
  28. {
  29. va.pd(i);
  30. }
  31. if(s[i]==b)
  32. {
  33. vb.pd(i);
  34. }
  35. }
  36. va.pd(n+1);
  37. vb.pd(n+1);
  38. ll ans=0;
  39. for(int i=0;i<vb.size()-1;i++)
  40. {
  41. int r=lower_bound(va.begin(),va.end(),vb[i]-k+1)-va.begin();
  42. if(va[r]>vb[i]-k+1)
  43. {
  44. r--;
  45. }
  46. ans+=r+1;
  47. //cout<<r+1<<" "<<va[r]<<" "<<vb[i]<<" "<<ans<<endl;
  48. }
  49. cout<<ans<<endl;
  50. }
  51. int main()
  52. {
  53. ios::sync_with_stdio(0);
  54. cin.tie(0);
  55. cout.tie(0);
  56. int tn=1;
  57. //cin>>tn;
  58. while(tn--)
  59. {
  60. solve();
  61. }
  62. return 0;
  63. }

试题 H: 整数删除.本题总分:20 

 线段树+并查集

对于每个点并查集维护左父亲和右父亲。对于每次操作线段树找到最左侧最小下标,然后返回,

这个点的左父亲等于这个点左边的点的左父亲,右同理,然后线段树修改值即可

复杂度 O(KlogN)

可以也采用set存点值和下标,然后+并查集

复杂度也是O(KlogN)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define endl '\n'
  5. #define x first
  6. #define y second
  7. #define pd push_back
  8. #define pii pair<int,ll>
  9. const int maxn=5e5+10;
  10. int n,k;
  11. ll a[maxn];
  12. int l[maxn],r[maxn],f[maxn];
  13. int findl(int x)
  14. {
  15. return x==l[x]?x:l[x]=findl(l[x]);
  16. }
  17. int findr(int x)
  18. {
  19. return x==r[x]?x:r[x]=findr(r[x]);
  20. }
  21. ll tr[maxn<<4];
  22. void up(int rt)
  23. {
  24. tr[rt]=min(tr[rt<<1],tr[rt<<1|1]);
  25. }
  26. void build(int rt,int l,int r)
  27. {
  28. tr[rt]=a[l];
  29. if(l==r)return;
  30. int mid=l+r>>1;
  31. build(rt<<1,l,mid);
  32. build(rt<<1|1,mid+1,r);
  33. up(rt);
  34. }
  35. pii cha(int rt,int l,int r)
  36. {
  37. if(l==r)
  38. {
  39. return {l,tr[rt]};
  40. }
  41. int mid=l+r>>1;
  42. pii ans;
  43. if(tr[rt<<1]<=tr[rt<<1|1])
  44. {
  45. ans=cha(rt<<1,l,mid);
  46. }else
  47. {
  48. ans=cha(rt<<1|1,mid+1,r);
  49. }
  50. return ans;
  51. }
  52. void add(int rt,int l,int r,int id,ll val)
  53. {
  54. if(id==l&&id==r)
  55. {
  56. tr[rt]+=val;
  57. a[l]=tr[rt];
  58. return;
  59. }
  60. int mid=l+r>>1;
  61. if(l<=id&&id<=mid)add(rt<<1,l,mid,id,val);
  62. else if(id>mid&&id<=r)add(rt<<1|1,mid+1,r,id,val);
  63. up(rt);
  64. }
  65. /*
  66. 5 3
  67. 1 4 2 8 7
  68. 5 4
  69. 1 4 2 8 7
  70. 5 5
  71. 1 4 2 8 7
  72. */
  73. void solve()
  74. {
  75. cin>>n>>k;
  76. l[0]=0;l[n+1]=0;
  77. r[0]=0;r[n+1]=0;
  78. for(int i=1;i<=n;i++)
  79. {
  80. cin>>a[i];
  81. l[i]=i;r[i]=i;
  82. f[i]=1;
  83. }
  84. build(1,1,n);
  85. while(k--)
  86. {
  87. ll mi=1e18,id=-1;
  88. // for(int i=1;i<=n;i++)//可用线段树优化
  89. // {
  90. // if(mi>a[i])
  91. // {
  92. // mi=a[i];
  93. // id=i;
  94. // }
  95. // }
  96. pii i=cha(1,1,n);
  97. id=i.x;mi=i.y;
  98. f[id]=0;
  99. l[id]=findl(l[id-1]);
  100. r[id]=findr(r[id+1]);
  101. if(l[id]>=1)add(1,1,n,l[id],mi);
  102. if(r[id]<=n)add(1,1,n,r[id],mi);
  103. add(1,1,n,id,1e17);
  104. // a[l[id]]+=a[id];
  105. // a[r[id]]+=a[id];
  106. // a[id]=1e18;
  107. // for(int i = 1; i <= n; i++)
  108. // {
  109. // if(f[i])
  110. // {
  111. // cout << a[i] << " ";
  112. // }
  113. // }
  114. // cout<<endl;
  115. }
  116. int ff=1;
  117. for(int i = 1; i <= n; i++)
  118. {
  119. if(f[i])
  120. {
  121. if(ff)ff=0;
  122. else cout<<" ";
  123. cout << a[i] ;
  124. }
  125. }
  126. }
  127. int main()
  128. {
  129. ios::sync_with_stdio(0);
  130. cin.tie(0);
  131. cout.tie(0);
  132. int tn=1;
  133. //cin>>tn;
  134. while(tn--)
  135. {
  136. solve();
  137. }
  138. return 0;
  139. }

试题 I: 景区导游 .本题总分:25 分

倍增,由于要按顺序去游览点,考虑起点那么只有A1,A2,对于2-k的点都是以A1为起点,那么其实路都差不多,假设在这之中p点不去,减去p-1到p的路径值减去p到p+1的路径值,加上p-1到p+1的路径值即可

复杂度O(NlogN+KlogN)

对于加减路径值也可以用树链剖分或lct 复杂度O(NlogN+KlogN)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. using ll = long long;
  4. const int N = 2e5 + 10;
  5. int h[N], e[N], w[N], ne[N], idx = 0;
  6. int lg[N], p[N][20], deep[N], a[N];
  7. ll dis[N], n, k, sum = 0;
  8. void dfs(int lst, int now) {
  9. deep[now] = deep[lst] + 1;
  10. p[now][0] = lst;
  11. for (int i = 1; (1 << i) <= deep[now]; i++)
  12. p[now][i] = p[p[now][i - 1]][i - 1];
  13. for (int i = h[now]; i; i = ne[i]) {
  14. int to = e[i], cost = w[i];
  15. if (to != lst) {
  16. dis[to] = dis[now] + cost;
  17. dfs(now, to);
  18. }
  19. }
  20. }
  21. int lca(int u, int v) {
  22. if (deep[u] < deep[v]) swap(u, v);
  23. while (deep[u] > deep[v])
  24. u = p[u][lg[deep[u] - deep[v]]];
  25. if (u == v) return u;
  26. else {
  27. for (int i = lg[deep[u]]; i >= 0; i--) {
  28. if (p[u][i] != p[v][i])
  29. u = p[u][i], v = p[v][i];
  30. }
  31. }
  32. return p[u][0];
  33. }
  34. inline void add(int u, int v, int t) {
  35. e[++idx] = v, w[idx] = t, ne[idx] = h[u], h[u] = idx;
  36. }
  37. inline ll ask(int u, int v) {
  38. if (u == 0 || v == 0) return 0;
  39. else return dis[u] + dis[v] - 2 * dis[lca(u, v)];
  40. }
  41. inline ll query(int i) {
  42. return ask(a[i - 1], a[i + 1]) - ask(a[i - 1], a[i]) - ask(a[i], a[i + 1]);
  43. }
  44. int main() {
  45. cin >> n >> k;
  46. for (int i = 1; i < n; i++) {
  47. int u, v, t;
  48. cin >> u >> v >> t;
  49. add(u, v, t);
  50. add(v, u, t);
  51. }
  52. for (int i = 2; i <= n; i++)lg[i] = lg[i >> 1] + 1;
  53. dfs(0, 1);
  54. for (int i = 1; i <= k; i++)cin >> a[i];
  55. for (int i = 2; i <= k; i++)sum += ask(a[i - 1], a[i]);
  56. for (int i = 1; i <= k; i++)cout << sum + query(i) << ' ';
  57. }

试题 J: 砍树 .本题总分:25 分

倍增+树上差分,对于一个数对,我们对数对路径上的值+1,最后看是否有一条边的左右点的点值相等

复杂度O(NlogN+N)

其实要对于数对路径值+1,也可以使用树链剖分来写,这样复杂度也是O(NlogN)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define endl '\n'
  5. #define x first
  6. #define y second
  7. #define pd push_back
  8. #define pii pair<int,ll>
  9. const int maxn=1e5+10;
  10. struct beizeng
  11. {
  12. int dp[22][maxn],deep[maxn];
  13. int val[maxn];
  14. vector<int>v[maxn];
  15. void add(int a,int b)
  16. {
  17. v[a].pd(b);
  18. v[b].pd(a);
  19. }
  20. void dfs(int x,int fa)
  21. {
  22. //dft[op]=x;
  23. //df[x]=op++;
  24. deep[x]=deep[fa]+1;
  25. dp[0][x]=fa;
  26. for(int i=1;(1<<i)<=deep[x];i++)
  27. {
  28. dp[i][x]=dp[i-1][dp[i-1][x]];
  29. }
  30. for(int y:v[x])
  31. {
  32. if(y==fa)continue;
  33. dfs(y,x);
  34. }
  35. }
  36. void dfs2(int x,int fa)
  37. {
  38. for(int y:v[x])
  39. {
  40. if(y==fa)continue;
  41. dfs2(y,x);
  42. val[x]+=val[y];
  43. }
  44. }
  45. int lca(int a,int b)
  46. {
  47. if(deep[a]>deep[b])swap(a,b);
  48. for(int i=20;i>=0;i--)
  49. {
  50. if(deep[a]<=deep[b]-(1<<i))
  51. b=dp[i][b];
  52. }
  53. if(a==b)
  54. return a;
  55. for(int i=20;i>=0;i--)
  56. {
  57. if(dp[i][a]!=dp[i][b])
  58. {
  59. a=dp[i][a];
  60. b=dp[i][b];
  61. }
  62. }
  63. return dp[0][a];
  64. }
  65. }tree;
  66. int n,m;
  67. int a[maxn],b[maxn];
  68. void solve()
  69. {
  70. cin>>n>>m;
  71. for(int i=1;i<n;i++)
  72. {
  73. cin>>a[i]>>b[i];
  74. tree.add(a[i],b[i]);
  75. }
  76. tree.dfs(1,0);
  77. for(int i=1;i<=m;i++)
  78. {
  79. int x,y;
  80. cin>>x>>y;
  81. int c=tree.lca(x,y);
  82. tree.val[x]++;tree.val[y]++;
  83. tree.val[c]--;tree.val[tree.dp[0][c]]--;
  84. }
  85. tree.dfs2(1,0);
  86. int ans=-1;
  87. for(int i=n-1;i>=1;i--)
  88. {
  89. if(tree.val[a[i]]==m&&tree.val[b[i]]==m)
  90. {
  91. ans=i;
  92. break;
  93. }
  94. }
  95. cout<<ans<<endl;
  96. }
  97. int main()
  98. {
  99. ios::sync_with_stdio(0);
  100. cin.tie(0);
  101. cout.tie(0);
  102. int tn=1;
  103. //cin>>tn;
  104. while(tn--)
  105. {
  106. solve();
  107. }
  108. return 0;
  109. }

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

闽ICP备14008679号