日常训练补题(第四周)
7-10 红色警报 - SMU 2024 spring 天梯赛2(补题) (pintia.cn)
题解:这题是一道暴力思维题
我们需要先统计一下最初的点的连通块
然后在一个个删除,每删除一次就跑一个并查集,在统计连通块的个数,然后对比前一次,看看连通块有没有变多即可
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e5+10,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<int,int> PII; int kmp(int a,int k,int p) { int ans=1; while (k) { if(k&1) ans=ans*a%p; k>>=1; a=a*a; } return ans; } int fa[N]; int find(int x) { if(fa[x]==x) return x; return fa[x]=find(fa[x]); } void add(int x,int y) { x=find(x),y=find(y); if(x!=y) { fa[x]=y; } return; } int x[N],y[N]; map<int,int> mp; void solve() { int n,m; cin>>n>>m; for(int i=0;i<n;i++) { fa[i]=i; } for(int i=1;i<=m;i++) { int v,u; cin>>v>>u; add(v,u);
7-15 特殊堆栈 - SMU 2024 spring 天梯赛2(补题) (pintia.cn)
题解:这道题就是类似于模拟,但是我们需要处理中位数
思维一:用一个栈每次输入输出,记录这个栈里有没有东西,没有东西我们就需要返回错误
然后用对顶堆的思维去维护一下中位数即可 但是这里用优先队列不能用,因为不能删除我们插入的数,所以我们改用
multiset 这个函数相当于没有去重功能的set 然后用迭代器二分跑一下我们要输出元素的位置即可
输出就输出当个堆中间那个即可
思维二:还是这个中位数的问题,我们其实可以不用对顶堆
我们用一个vector然后删除的时候和上面一样二分删除 用迭代器
插入也是二分插入,二分插入让数组有序化然后正常输出中位数即可
void solve() { int n; cin>>n; vector<int> a; stack<int> q; vector<int> ::iterator it; int r=0; for(int i=1;i<=n;i++) { string s; cin>>s; int x; if(s=="Pop") { if(q.size()!=0) { it= lower_bound(a.begin(),a.end(),q.top()); a.erase(it); cout<<q.top()<<endl; q.pop(); } else { cout<<"Invalid"<<endl; } } if(s=="Push") { cin>>x; q.push(x); it = lower_bound(a.begin(),a.end(),x); a.insert(it,x); } if(s=="PeekMedian") { if(!q.empty()) { int y=a.size(); if(y%2) y++; y/=2; cout<<a[y-1]<<endl; } else { cout<<"Invalid"<<endl; } } } } signed main(){ // std::ios::sync_with_stdio(false); // std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
7-11 排座位 - SMU 2024 spring 天梯赛2 (pintia.cn)
题解:这道题少了3分,因为题目看漏了一个条件,就是朋友的朋友也是朋友,我直接判断的朋友的朋友不是朋友,所以少3分
这道题我们可以用并查集维护一下即可,就看看敌人有没有共同的祖先即可满分
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=9e3+10,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<int,int> PII; int kmp(int a,int k,int p) { int ans=1; while (k) { if(k&1) ans=ans*a%p; k>>=1; a=a*a; } return ans; } int a[N][N]; vector<int> b[N]; int fa[N]; int find(int x) { if(fa[x]==x) return x; else return fa[x]=find(fa[x]); } void add(int x,int y) { x=find(x),y=find(y); if(x!=y) { fa[x]=y; } } void solve() { int n; cin>>n; int m; cin>>m; int k; cin>>k; for(int i=1;i<=n;i++) { fa[i]=i; } for(int i=1;i<=m;i++) { int x,y; int op; cin>>x>>y>>op; if(op==-1) { a[x][y]=-1; a[y][x]=-1; } else { a[x][y]=1; a[y][x]=1; add(x,y); b[x].push_back(y); b[y].push_back(x); } } while (k--) { int x,y; cin>>x>>y; if(a[x][y]==0) { cout<<"OK"<<endl; } else if(a[x][y]==1) { cout<<"No problem"<<endl; } else if(a[x][y]==-1) { int f=0; if(find(x)==find(y)) f=1; if(f) { cout<<"OK but..."<<endl; } else { cout<<"No way"<<endl; } } } } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
7-13 肿瘤诊断 - SMU 2024 spring 天梯赛2 (pintia.cn)
题解:一道宽搜题目,我们开一个三维数组去记录一下 这个是一个有前 后 上 下 左 右 6个方向,我们每一次直接搜索一下6个方向即可,如果满足条件那么加上体积即可
注意人家是一个立体的有上面和下面 不单单一个平面
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=9e3+10,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<int,int> PII; int kmp(int a,int k,int p) { int ans=1; while (k) { if(k&1) ans=ans*a%p; k>>=1; a=a*a; } return ans; } int dir[6][3]={{0,1,0},{0,-1,0},{0,0,-1},{0,0,1},{1,0,0},{-1,0,0}}; int a[70][1300][130]; int ans=0; int vis[70][1300][130]; int n,m,l,t; int bfs(int u,int x,int y) { queue<int> q[3]; vis[u][x][y]=1; q[0].push(u); q[1].push(x); q[2].push(y); int sum=1; while (!q[0].empty()) { int uq=q[0].front(); int xq=q[1].front(); int yq=q[2].front(); q[0].pop(); q[1].pop(); q[2].pop(); for(int i=0;i<6;i++) { int uu=uq+dir[i][0]; int xx=xq+dir[i][1]; int yy=yq+dir[i][2]; if(uu>=1 && uu<=l && xx>=1 && xx<=n && yy>=1 && yy<=m && vis[uu][xx][yy]!=1 && a[uu][xx][yy]==1) { sum++; q[0].push(uu); q[1].push(xx); q[2].push(yy); vis[uu][xx][yy]=1; } } } if(sum>=t) { return sum; } else return 0; } void solve() { cin>>n>>m>>l>>t; for(int i=1;i<=l;i++) { for(int j=1;j<=n;j++) { for(int z=1;z<=m;z++) { cin>>a[i][j][z]; } } } for(int i=1;i<=l;i++) { for(int j=1;j<=n;j++) { for(int z=1;z<=m;z++) { if(a[i][j][z]==1 && vis[i][j][z]!=1) { ans+=bfs(i,j,z); } } } } cout<<ans<<endl; } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
7-9 哈利·波特的考试 - SMU 2024 spring 天梯赛3(补题) (pintia.cn)
题解:这个题当时缺了一个点,是一个判断0的点
首先我们直接floyd求各个点的最短路,然后在暴力去跑每一个点到其他点的距离找最大判断一下即可
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e5+10,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<int,int> PII; int kmp(int a,int k,int p) { int ans=1; while (k) { if(k&1) ans=ans*a%p; k>>=1; a=a*a; } return ans; } int d[2000][2000]; int n,m; vector<int> c[N]; void floyd()//一个贪心去找每一个节点的中间最优节点 { for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { d[i][j]=min(d[i][j],d[i][k]+d[k][j]); } } } } void solve() { cin>>n>>m; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(i==j) d[i][j]=0; else d[i][j]=INF; } } for(int i=1;i<=m;i++) { int a,b,su; cin>>a>>b>>su; c[a].push_back(b); c[b].push_back(a); d[a][b]=su; d[b][a]=su; } int f=0; floyd(); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(i==j) continue; if(d[i][j]==INF) f=1; } } if(f) { cout<<0<<endl; return; } int k=0; int ans=INF; for(int i=1;i<=n;i++) { int sum=0; for(int j=1;j<=n;j++) { if(i==j) continue; sum=max(sum,d[i][j]); } if(sum<ans) { k=i; ans = min(ans, sum); } } cout<<k<<" "<<ans<<endl; } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
7-8 连续因子 - SMU 2024 spring 天梯赛3(补题) (pintia.cn)
题解:暴力枚举即可
因为这个东西的长度最大不超过14,否则乘超过题目涉及范围
首先我们枚举长度,从2开始
判断从2开始乘超过n就结束
然后从3开始以此类推
然后符合条件记录一下头和尾,还有长度。输出即可
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e6+10,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<int,int> PII; int kmp(int a,int k,int p) { int ans=1; while (k) { if(k&1) ans=ans*a%p; k>>=1; a=a*a; } return ans; } bool pr(int x) { for(int i=2;i<=sqrt(x);i++) { if(x%i==0) return false; } return true; } void solve() { int n; cin>>n; int si=0; int st=0; int en=0; if(pr(n)) { cout<<1<<endl; cout<<n<<endl; } else { for(int i=2;i<= sqrt(n);i++) { int sum=1; for(int j=i;sum*j<=n;j++) { sum*=j; if(n%sum==0 && j-i+1>si) { st=i; si=j-i+1; en=j; } } } cout<<si<<endl; for(int i=st;i<=en;i++) { cout<<i; if(i!=en) cout<<"*"; } } } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
7-12 病毒溯源 - SMU 2024 spring 天梯赛3 (pintia.cn)
题解:这是一个树题
首先我们先存个图,注意这里存完要排个序,保证小的点在前面,这样跑出来的就是最小序列
然后我们跑树丛叶子结点向上跑 每一次记录最长的值
这里我们用一个数组存链
比如对于这个长链来说,根节点u当下标存的下一个节点,这样我们就可以靠根节点不断向下跑链上的数字了
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e5+10,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<int,int> PII; int kmp(int a,int k,int p) { int ans=1; while (k) { if(k&1) ans=ans*a%p; k>>=1; a=a*a; } return ans; } vector<int> su[N]; int gen[N]; int a[N]; int dfs(int u) { int sum=0; a[u]=-1; for(int i=0;i<su[u].size();i++) { int x=su[u][i]; int d=dfs(x); if(d>sum) { sum=d; a[u]=x; } } return sum+1; } void solve() { int n; cin>>n; for(int i=0;i<n;i++) { int k; cin>>k; for(int j=1;j<=k;j++) { int x; cin>>x; gen[x]=1; su[i].push_back(x); } sort(su[i].begin(),su[i].end()); } int rr=0; for(int i=0;i<n;i++) { if(!gen[i]) { rr=i; } } cout<<dfs(rr)<<endl; cout<<rr; while (a[rr]!=-1) { cout<<" "<<a[rr]; rr=a[rr]; } } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
7-12 这是二叉搜索树吗? - SMU 2024 spring 天梯赛2(补题) (pintia.cn)
题解:一道数据结构题
我们直接按照题目要求构建这个排序树,然后分别构建正常的和镜像的
然后在递归的去吧后序结果跑出来,如果后序里节点数不够那没结束不可行
我们先处理正常树
分左右子树去递归即可
while (i<=r && a[i]<a[l]) i++; while (j>l && a[j]>=a[l]) j--;
get(l+1,j);
get(i,r);
这样我们就可以建起来,每一次分成两堆,最后一个个按照左边插入成后序
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e5+10,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<int,int> PII; int kmp(int a,int k,int p) { int ans=1; while (k) { if(k&1) ans=ans*a%p; k>>=1; a=a*a; } return ans; } bool f; int a[N]; vector<int> hou; void get(int l,int r) { if(l>r) return; int i=l+1,j=r; if(!f) { while (i<=r && a[i]<a[l]) i++; while (j>l && a[j]>=a[l]) j--; } else { while (i<=r && a[i]>=a[l]) i++; while (j>l && a[j]<a[l]) j--; } if(i-j!=1) return; get(l+1,j); get(i,r); hou.push_back(a[l]); } void solve() { int n; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; } get(1,n); if(hou.size()!=n) { f= true; hou.clear(); get(1,n); } if(hou.size()==n) { cout<<"YES"<<endl; for(int i=0;i<hou.size();i++) { cout<<hou[i]; if(i!=hou.size()-1) cout<<" "; } } else cout<<"NO"<<endl; } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }