补题场链接:https://pintia.cn/problem-sets/1373141720280027136

本次选拔赛除后三题以外,其余的题目难度都不是很大,简单筛选一下大家的基础。请大家这段时间加油刷题,好好准备 4月24日 的天梯赛正赛。

L1-1 买不起的肥宅水

Solution

直接算即可,因为瓶数一定是整数所以取整。

Code

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
const int N = 6e6 + 7, M = 5e6 + 7, mod = 1e9 + 7, INF = 0x3f3f3f3f;
const double PI = acos(-1.0), eps = 1e-8;double n;signed main()
{scanf("%lf", &n);cout << int(50 / n) <<endl;return 0;
}

L1-2 分解分解再分解

Solution

分解质因数模板题。

Code

#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
const int N = 6e6 + 7, M = 5e6 + 7, mod = 1e9 + 7, INF = 0x3f3f3f3f;
const double PI = acos(-1.0), eps = 1e-8;int n, m;
int ans[N], tot;signed main()
{scanf("%lld", &n);for(int i = 2; i <= n / i; ++ i) {if(n % i == 0) {ans[ ++ tot] = i;while(n % i == 0) n /= i;}}if(n > 1) ans[ ++ tot] = n;cout << tot << endl;for(int i = 1; i <= tot; ++ i) {printf("%lld%s", ans[i], i == tot ? "\n" : " ");}return 0;
}

L1-3 阅览室

直接模拟即可。

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
const int N = 1e4 + 7, M = 5e6 + 7, mod = 1e9 + 7, INF = 0x3f3f3f3f;
const double PI = acos(-1.0), eps = 1e-8;double sum;
int Time[N];
bool vis[N];
int t, tot;signed main()
{scanf("%d", &t);char ch;int id, h, m;while(scanf("%d %c %d:%d", &id, &ch, &h, &m) != EOF) {if(id == 0) {memset(vis, 0, sizeof vis);memset(Time, 0, sizeof Time);if(tot == 0) puts("0 0");else printf("%d %d\n", tot, int(sum / tot + 0.5));sum = 0.0, tot = 0;}if(ch == 'S') {vis[id] = 1;Time[id] = h * 60 + m;}else if(ch == 'E' && vis[id]) {vis[id] = 0;sum += h * 60 + m - Time[id];++ tot;}}return 0;
}

L1-4 桥短几何

直接爆搜即可。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
typedef long long ll;
typedef pair<int, int> pii;
int n, mp[110][110], dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
int island1[10000], island2[10000], idx1, idx2;
void bfs(int x, int y, int color)
{queue<pii> q;q.push({x, y});mp[x][y] = color;while(q.size()){pii t = q.front();q.pop();for (int i = 0; i < 4; i ++){int nx = t.first + dx[i], ny = t.second + dy[i];if (nx < 1 || nx > n || ny < 1 || ny > n) continue;if (mp[nx][ny] == 0 || mp[nx][ny] == color) continue;mp[nx][ny] = color;q.push({nx, ny});}}
}
int main()
{cin >> n;for (int i = 1; i <= n; i ++)for (int j = 1; j <= n; j ++)cin >> mp[i][j];for (int i = 1; i <= n; i ++){int flag = 0;for (int j = 1; j <= n; j ++)if (mp[i][j] == 1){bfs(i, j, 2);flag = 1;break;}if (flag) break;}for (int i = 1; i <= n; i ++){for (int j = 1; j <= n; j ++){if (mp[i][j] == 1) island1[idx1 ++] = (i - 1) * n + j;if (mp[i][j] == 2) island2[idx2 ++] = (i - 1) * n + j;}}int ans = INF;for (int i = 0; i < idx1; i ++){for (int j = 0; j < idx2; j ++){int x1 = island1[i] / n + 1, y1 = island1[i] % n;int x2 = island2[j] / n + 1, y2 = island2[j] % n;if (y1 == 0) x1 -= 1, y1 = n;if (y2 == 0) x2 -= 1, y2 = n;ans = min(ans, abs(x1 - x2) + abs(y1 - y2));}}cout << ans - 1 << endl;return 0;
}

或者直接计算。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int n,Min=1e5+10;
int g[110][110];
int p[10010][2],s;
int main()
{cin>>n;for(int i=0;i<n;i++)for(int j=0;j<n;j++){scanf("%d",&g[i][j]);}for(int i=0;i<n;i++){int flag=0;for(int j=0;j<n;j++){if(g[i][j]==1) {g[i][j]=2;p[s][0]=i;p[s++][1]=j;flag=1;break;}}if(flag) break;}for(int i=0;i<n;i++)for(int j=0;j<n;j++){if(g[i][j]==1&&(g[i-1][j]==2||g[i+1][j]==2||g[i][j-1]==2||g[i][j+1]==2)){g[i][j]=2;p[s][0]=i;p[s++][1]=j;}}for(int i=0;i<n;i++){for(int j=0;j<n;j++){if(g[i][j]==1){for(int k=0;k<s;k++){int m=abs(p[k][0]-i)+abs(p[k][1]-j)-1;Min=min(m,Min);}}}}printf("%d",Min);return 0;
}

L1-5 STL

注意合法的情况就是指正常 pair 的用法,所以 pair<int,pair<int,int>> 显然也是成立的。

直接递归模拟即可。

#include<bits/stdc++.h>
using namespace std;string ans;
bool flag = 1;
int n;void solve()
{string s;cin >> s;if(s == "pair") {ans += "pair<";solve();ans += ",";solve();ans += ">";}else if(s == "int") {ans += "int";}else flag = 0;
}int main()
{ans = "";string s;flag = 1;cin >> n;solve();cin >> s;if(flag == 0) {puts("Error occurred");}else if(s.size() != 0) puts("Error occurred");else cout << ans << endl;return 0;
}

L2-1 部落

并查集,开一个桶计算有多少个点即可。

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
const int N = 1e4 + 7, M = 5e6 + 7, mod = 1e9 + 7, INF = 0x3f3f3f3f;
const double PI = acos(-1.0), eps = 1e-8;int n, m;
int fa[N];
int vis[N];
int ans1, ans2;int Find(int x)
{if(fa[x] == x) return x;return fa[x] = Find(fa[x]);
}void Union(int x, int y)
{int fx = Find(x);int fy = Find(y);fa[fy] = fx;
}int main()
{scanf("%d", &n);for(int i = 0; i <= N - 7; ++ i)fa[i] = i;for(int i = 1; i <= n; ++ i) {int k;scanf("%d", &k);int father;if(k > 0) {scanf("%d", &father);if(vis[father] == 0) vis[father] = 1, ans1 ++ ;}for(int j = 1; j < k; ++ j) {int x;scanf("%d", &x);if(vis[x] == 0) vis[x] = 1, ans1 ++ ;Union(father, x);}}for(int i = 1; i <= ans1; ++ i)if(fa[i] == i) ans2 ++ ;cout << ans1 << " " << ans2 << endl;int q;scanf("%d", &q);while(q -- ) {int x, y;scanf("%d%d", &x, &y);if(Find(x) == Find(y)) puts("Y");else puts("N");}return 0;
}

L2-2 XOR


Solution

考虑到数据范围只有1e9,也就是二进制仅30位, 可以发现,当三个二进制数最高位相同时,则仅需一次执行必然可以将其中两个变小,所以最多只有两个二进制最高位相同的数相邻的情况,所以数据范围骤降到60,这时候随便循环乱搞即可,甚至O(n^4)都是可以过的。

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false)
using namespace std;typedef long long ll;
typedef pair<int,int> pii;
const int inf = 0x3f3f3f3f;
const double eps = 1e-10;
const double pi = acos(-1.0);
const ll mod = 1e9 + 7;const int N = 2e5 + 10;
int a[N];int main()
{int t;cin>>t;while(t--){int n;cin>>n;for(int i = 0;i < n;++i)    cin>>a[i];if(n == 2) {puts("-1");continue;}if(n >= 61){printf("%d\n",1);continue;}int res = inf;for(int i = 1;i < n;++i){int l = 0;int r = 0;for(int j = i-1;j >= 0;--j){for(int k = i;k < n;++k){l = 0,r = 0;for(int p = j;p < i;++p) l ^= a[p];for(int q = i;q <= k;++q)  r ^= a[q];if(l > r){res = min(res,k - j - 1);} }}}if(res != inf)printf("%d\n",res);else puts("-1");}return 0;
}

L3-1 Simple Tree Problem

这题的做法很多

Solution 1

  • 考虑从根开始进行深度优先搜索,对于一颗树的子树其 DFS序必然时连续的。
  • 对于一个节点,在进入这颗节点子树之前计算一下比它权值大的点的个数,在dfs完成后再计算一遍权值大于它的节点个数,那么增加的值就为该节点的答案。至于怎么计算权值比它大的个数,我们可以将权值离散化后维护一颗权值树状数组即可
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
vector<int>v[maxn];
int ans[maxn];
int bit[maxn];
int a[maxn],b[maxn];
int m;
void modify(int x){while(x <= m){bit[x]++,x+=x&-x;};}
int query(int x){int ans=0;while(x){ans+=bit[x],x-=x&-x;}return ans;};
void dfs(int now)
{modify(a[now]);int pre = query(m)-query(a[now]);for(int i = 0;i < v[now].size();++i)dfs(v[now][i]);int to = query(m)-query(a[now]);ans[now] = to-pre;
}
int main()
{int n;scanf("%d",&n);for(int i = 1;i <= n;++i)scanf("%d",&a[i]),b[i] = a[i];sort(b+1,b+1+n);m = unique(b+1,b+1+n)-b-1;for(int i = 1;i <= n;++i)a[i] = lower_bound(b+1,b+1+m,a[i])-b;for(int i = 2;i <= n;++i){int x;scanf("%d",&x);v[x].push_back(i);}dfs(1);for(int i = 1;i <= n;++i)printf("%d\n",ans[i]);return 0;
}

Solution 2

  • 因为答案询问的是子树,对于一颗树的子树有一个很重要的性质就是一棵树的子树的dfs一定是连续的。

  • 通过这个性质我们就可以把树上问题转化为区间问题,即对于一个序列求一个区间内比某个数大的数个数。这个问题

    可以使用可持久化线段树或者CDQ分治解决

  #include <bits/stdc++.h>using namespace std;const int maxn=2e5+5;int a[maxn],b[maxn];int ls[maxn*40],rs[maxn*40],root[maxn],tree[maxn*40];int L[maxn],R[maxn];int dfsx[maxn];int t1,tot;vector<int>v[maxn];int n,m;void dfs(int now){dfsx[++t1] = now;L[now] = t1;for(int i = 0;i < v[now].size();++i)dfs(v[now][i]);R[now] = t1;}int creatnode(int preroot){int tmp = ++tot;tree[tmp] = tree[preroot]+1;ls[tot] = ls[preroot];rs[tot] = rs[preroot];return tmp;}void Insert(int &rt,int prert,int l,int r,int id){rt = creatnode(prert);if(l==r)return;int mid = l+r>>1;if(id <= mid)Insert(ls[rt],ls[prert],l,mid,id);elseInsert(rs[rt],rs[prert],mid+1,r,id);}int Query(int s,int e,int l,int r,int k){if(l >= k)return tree[e]-tree[s];int mid = l+r>>1;int ans = 0;if(k <= mid){ans+=tree[rs[e]]-tree[rs[s]];ans+=Query(ls[s],ls[e],l,mid,k);}elseans+=Query(rs[s],rs[e],mid+1,r,k);return ans;}int main(){scanf("%d",&n);for(int i = 1;i <= n;++i)scanf("%d",&a[i]),b[i]=a[i];sort(b+1,b+1+n);m = unique(b+1,b+1+n)-b-1;for(int i = 1;i <= n;++i)a[i] = lower_bound(b+1,b+1+n,a[i])-b;int x;for(int i = 2;i <= n;++i){scanf("%d",&x);v[x].push_back(i);}dfs(1);for(int i = 1;i <= n;++i)Insert(root[i],root[i-1],1,n,a[dfsx[i]]);for(int i = 1;i <= n;++i)printf("%d\n",Query(root[L[i]-1],root[R[i]],1,n,a[i]+1));return 0;}

Solution 3

  • 对于树上子树信息问题有一个经典算法叫做树上启发式合并。这个题可以通过树上启发式合并在 O(nlognlogn)O(nlognlogn)O(nlognlogn) 的复杂度内解决,感兴趣的可以自己学一下。

Solution 4

  • 最后再介绍一种比较暴力的方法,对每一个节点维护一个权值线段树(当然需要动态开点)。

L3-2 序列

Solution

我们可以直接暴力枚举第一个区间的左端点,然后尺取,贪心地移动右端点,与此同时同样尺取第二个区间,理论时间复杂度为 O(n3)O(n^3)O(n3) ,但是中间可以剪枝,如果已经不是最优解就直接 break,然后跑得贼快。

也可以先用尺取法求出最大区间,用 set 维护,然后再找第二个区间,时间复杂度 O(n2logn)O(n^2logn)O(n2logn)。

Code

#include <bits/stdc++.h>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <queue>
using namespace std;
typedef long long ll;
typedef int itn;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
const int N = 6e6 + 7, M = 5e6 + 7, mod = 1e9 + 7, INF = 0x3f3f3f3f;
const double PI = acos(-1.0), eps = 1e-8;int n, m, t, kcase;
int a[N];
int col[N];
int ans = -INF;void solve()
{ans = -INF;memset(col, 0, sizeof col);scanf("%d", &n);for(int i = 0; i < n; ++ i)scanf("%d", &a[i]);//右指针始终每轮开始的时候都固定在左指针的左边一位,这样每轮开始就可以把当前l指向的结点进行一次必要的 ++ 操作, 左指针维护 -- 操作, 右指针维护 ++ 操作for(int l = 0, r = -1, L, R; l < n; col[a[l ++ ]] -- ) {if(n - l <= ans) break;while(r < l - 1) col[a[ ++ r]] ++ ;while(r + 1 < n && col[a[r + 1]] <= 0) {col[a[ ++ r]] ++ ;for(L = r + 1, R = L - 1; L < n; col[a[L ++ ]] -- ) {if(n - L + 1 + r - l + 1 <= ans) break;while(R + 1 < n && col[a[R + 1]] <= 0)col[a[ ++ R]] ++ ;ans = max(ans, R - L + 1 + r - l + 1);}while(R < L - 1) col[a[ ++ R]] ++ ;//回到L-1while(R > L - 1) col[a[ R -- ]] -- ;}while(r > l - 1) col[a[r -- ]] -- ;//回到l-1}printf("%d\n", ans);return ;
}int main()
{scanf("%d", &t);while(t -- ) {printf("Case #%d: ", ++ kcase);solve();}return 0;
}

SWPU 2021年团队程序设计天梯赛选拔赛 题解相关推荐

  1. 2021年团体程序设计天梯赛-总决赛题解

    L2-2 病毒溯源 L2-4 哲哲打游戏 L3-2 还原文件 L1-1 人与神 (5 分) 跨界大神 L. Peter Deutsch 有一句名言:"To iterate is human, ...

  2. 2023团队程序设计天梯赛选拔赛

    1.Ltree的数据结构 T322022 Ltree的数据结构 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 主次关键字的排序 用结构体 比赛过程中,其它都很顺利,问题出在了名次上 ...

  3. 2021年团体程序设计天梯赛-总决赛L2题解

    2021年团体程序设计天梯赛-总决赛! L2-1 包装机 思路:模拟 代码: #include<bits/stdc++.h> using namespace std; int main() ...

  4. 2020团队程序设计天梯赛 L2-2 口罩发放 (25分)

    2020团队程序设计天梯赛 赛后听许多人感慨,火锅火锅吃不掉,彩票彩票刮不开,调和平均也调不和,而像我这种口罩发不下去的人也在大多数吧 L2-2 口罩发放 (25分) 为了抗击来势汹汹的 COVID1 ...

  5. 第六届团队程序设计天梯赛 全题目解析讲解

    B站已经录好视频合集:--------------------传送门--------------------- 题目是2021年4月天梯赛决赛原题: 题号 题目名称 L1-1 人与神 L1-2 两小时 ...

  6. 2022年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛 题解

    天梯赛 A题 总结 B题 C题 D题 E题 G题 H题 K题 A题 思路: 分两种情况: 1.除了最大的数 其他的都是与最大的数的和最大 2.最大的数与第二大的数的和最大 代码实现法一:利用pair的 ...

  7. GLPT团队程序设计天梯赛 2023正式赛

    2023.4.22 13:30-16:30 162分 团队1556分 L1-1 最好的文档 5 15990/21484(74.43%) 在一行中输出 Good code is its own best ...

  8. 2022年 GPLT 团队程序设计天梯赛 总结

    昨天,感觉一天都在忙天梯赛,也算打的满意了吧,分数141,有效分139,队伍拿了团队铜奖,学校排在山东省第九名. L1的题很稳,100分拿到了,L2-2也是一遍过,L2-1一个模拟,当时脑子浑了,就写 ...

  9. PTA|团队程序设计天梯赛-练习集题解(L1)

    L1-001 Hello World (5 分) 这道超级简单的题目没有任何输入. 你只需要在一行中输出著名短句"Hello World!"就可以了. 输入样例: 无 输出样例: ...

最新文章

  1. 转我们经理的一篇文章,业务流程实现的讨论,希望大家集思广议。
  2. Django从理论到实战(part16)--指定默认的参数
  3. dlgdata.cpp错误提示 解决方案
  4. 密码学原理与实践_到底什么是防火墙入侵检测密码学身份认证?如何高效建立网络安全知识体系?...
  5. Python基础学习总结、学习展望
  6. c语言popen函数多线程,关于多线程:多线程环境中的Python-Subprocess-Popen行为不一致...
  7. oracle+dg常用命令,DG 日常管理命令汇总
  8. Rockwell AB PLC 控制器EDS 更新下载更新方法
  9. 关于office2016和visio2016无法共存的问题
  10. 【代码笔记】RRDNet 网络
  11. Excel常用10个函数
  12. Markdown 常用数学符号和公式
  13. java百度地图离线开发_【“零起点”--百度地图手机SDK】如何使用离线地图?
  14. 10月24日程序员HTML5,【通知】10月24日程序员节放假1天
  15. NYOJ 1132 promise me a medal (判断两线段是否相交)
  16. Android NCNN识别文字(OCR)
  17. 【图像识别】基于模板匹配算法求解车牌识别问题matlab代码含GUI界面
  18. SpringMVC实现i18n和主题切换
  19. 【动态规划】什么是动态规划
  20. [附源码]Python计算机毕业设计大学生健康管理系统的设计与实现Django(程序+LW)

热门文章

  1. 一文看懂95%置信区间
  2. YOLOv5实现自定义对象训练与OpenVINO部署全解析
  3. 手把手用YOLO做目标检测
  4. 链表问题8——将单向链表按某值划分成左边小、中间相等、右边大的形式(进阶)
  5. Spring security获取当前用户
  6. 压缩工具gzip,bzip2,xz,zip,tar
  7. OC中的NSNumber、NSArray、NSString的常用方法
  8. Apache Tiles 学习(四)、Tiles实战
  9. Android中网络使用
  10. 《基于MFC的OpenGL编程》Part 1 A Primer