A. Maximum Square
题意:找最大的正方形边长
解:排序,贪心

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=1e5+10; int a[MAXN]; bool cmp(int x,int y){return x>y;} int main(){ int T; cin>>T; while(T--){ int n; cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; sort(a+1,a+1+n,cmp); int ans=0; for(int i=1;i<=n;i++){ ans++; if(a[i]>=ans)continue; else { ans--; break; } } cout<<ans<<endl; } return 0; }
B1. Character Swap (Easy Version)
题意:给两个字符串s和t,只能进行一次操作:交换s[i]和t[j]是否使得两个字符串相等。
解:1.两个字符串相同输出yes
2.两个字符串有一个位置不相同输出no
3.两个字符串有两个位置不相同,判断是否能根据交换来使得两个字符串相同
4.超过两个位置不相同,一定是不能够进行一次操作使得两个字符串相等

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=1e5+10; int a[30]; int b[30]; char s[MAXN]; char t[MAXN]; int main(){ int T; cin>>T; while(T--){ for(int i=0;i<30;i++)a[i]=0; for(int i=0;i<30;i++)b[i]=0; int n; cin>>n; cin>>s>>t; char ss; char tt; int cnt=0; bool ok=false; for(int i=0;i<n;i++){ if(s[i]!=t[i]&&!cnt){ ss=s[i]; tt=t[i]; cnt++; } else if(s[i]!=t[i]&&cnt==1){ if(ss==s[i]&&tt==t[i])ok=true,cnt++; else break; }else if(s[i]!=t[i]){ cnt++; break; } } if(cnt==0||(ok&&cnt==2))cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; }
B2. Character Swap (Hard Version)
其实与上题不同,我以为相同就做完hard版本直接交easy了……结果直接wa
题意:给两个字符串,进行最多2n次操作使得两个字符串相等
操作:选择s[i]和t[j]交换,如果能够相等输出yes并且输出交换方案
解:暴力交换就行了。

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=1e5+10; int a[30]; char s[MAXN]; char t[MAXN]; vector<int>vec[30]; pair<int,int>P[MAXN]; int main(){ int T; cin>>T; while(T--){ for(int i=0;i<30;i++)a[i]=0; int n; cin>>n; cin>>s>>t; for(int i=0;i<n;i++){ a[s[i]-'a']++; a[t[i]-'a']++; } bool ok=true; for(int i=0;i<30;i++){ if(a[i]%2){ ok=false;break; } } if(!ok)cout<<"No"<<endl; else{ cout<<"Yes"<<endl; int tot=0; for(int i=0;i<n;i++){ if(s[i]==t[i])continue; ok=false;int flag; for(int j=i+1;j<n;j++){ if(s[i]==s[j]){ ok=true; flag=j; break; } } if(ok){ P[tot].first=flag; P[tot++].second=i; s[flag]=t[i]; } else{ for(int j=i+1;j<n;j++){ if(s[i]==t[j]){ flag=j; break; } } t[flag]=s[flag]; P[tot].first=flag;P[tot++].second=flag; s[flag]=t[i]; P[tot].first=flag;P[tot++].second=i; } } cout<<tot<<endl; for(int i=0;i<tot;i++){ cout<<P[i].first+1<<' '<<P[i].second+1<<endl; } } } return 0; }
C. Tile Painting
题意:给一个长度为n的格子进行染色,问最多有多少种不同的颜色。
规定:n%|i-j|==0且|i-j|>1的格子颜色相等。
解:找循环节,n/lcm=gcd,答案就是所有因子的gcd

#include <bits/stdc++.h> using namespace std; typedef long long ll; int main(){ ll n; cin>>n; ll ans=n; for(ll i=2;i<=sqrt(n);i++){ if(n%i==0){ ans=__gcd(ans, i); ans=__gcd(ans,n/i); } } cout<<ans<<endl; return 0; }
D. 0-1 MST
题意:给一个完全图,其中m条边的权值为1,其余边的权值为0;求最小生成树。
解:当然优先选择权值为0的边,然后再选择权值为1的边。那么假设把权值为0的边全部连接起来,那么就剩权值为1的边没有连接。这个时候可能就被分成几个联通块,那么明显答案就是连通块的个数-1了。
怎么求这个连通块的个数?看了题解说是cf的老套路了?因为点多还是完全图,所以不能直接用kru or pri。
把所有的点放到集合s中,然后枚举每一个点u,对于u去找有没有权值为1的边,如果没有,那么这个点也是u联通的点

#include <bits/stdc++.h> using namespace std; const int MAXN=1e5+10; set<int>st,g[MAXN]; bool vis[MAXN]; void bfs(int x){ queue<int>que; que.push(x); st.erase(x); while(!que.empty()){ int u=que.front();que.pop(); if(vis[u])continue; vis[u]=true; for(auto it=st.begin();it!=st.end();){ int v=*it;it++; if(g[u].find(v)==g[u].end()){ st.erase(v); que.push(v); } } } } int main(){ int n,m; cin>>n>>m; for(int i=1;i<=m;i++){ int u,v; cin>>u>>v; g[u].insert(v); g[v].insert(u); } for(int i=1;i<=n;i++)st.insert(i); int ans=0; for(int i=1;i<=n;i++){ if(!vis[i]){ ans++; bfs(i); } } cout<<ans-1<<endl; return 0; }