Codeforces Round #599 (Div. 2)(A-D)

2020-01-14 21:14发布

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;
}
View Code

 

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;
}
View Code

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;
}
View Code

 

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;
}
View Code

 

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;
}
View Code

 

 

标签: