Codeforces Round #544 题解

A题

用scanf读入更加方便,之后只要计算差值即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef map<string,int> st;
const int N=5e5+10;
int main(){
    //ios::sync_with_stdio(false);
    int h1,m1,h2,m2;
    scanf("%02d:%02d",&h1,&m1);
    scanf("%02d:%02d",&h2,&m2);
    int x=h2-h1;
    int y=m2-m1;
    x=x*60+y;
    x/=2;
    int d1=x/60;
    int d2=x%60;
    printf("%02d:%02d",h1+d1+((m1+d2)/60),(m1+d2)%60);
}
View Code

B题

用一个桶来维护答案,取min求和即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef map<string,int> st;
const int N=5e5+10;
int a[N];
int cnt[N];
int main(){
    ios::sync_with_stdio(false);
    int n,k;
    cin>>n>>k;
    int i;
    for(i=1;i<=n;i++){
        cin>>a[i];
        a[i]%=k;
        cnt[a[i]]++;
    }
    int ans=0;
    ans+=cnt[0]/2;
    for(i=1;i<=k/2;i++){
        if(i!=k-i)
        ans+=min(cnt[i],cnt[k-i]);
        else{
            ans+=cnt[i]/2;
        }
    }
    cout<<ans*2<<endl;
}
View Code

C题

经典套路,枚举每个位置之后二分求当前位置的最大答案后取max

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef map<string,int> st;
const int N=5e5+10;
vector<int> num;
int find(int x){
    return lower_bound(num.begin(),num.end(),x+6)-num.begin();
}
int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    int i;
    for(i=1;i<=n;i++){
        int x;
        cin>>x;
        num.push_back(x);
    }
    sort(num.begin(),num.end());
    int ans=0;
    for(i=0;i<(num).size();i++){
        int x=num[i];
        int pos=find(x)-1;
        ans=max(ans,pos-i+1);
    }
    cout<<ans<<endl;
}
View Code

D题

用map+pair维护答案,只要求取最大的即可,这里要注意0的情况

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
typedef map<string,int> st;
const int N=5e5+10;
map<pll,int> m1;
int c[N],d[N];
int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}
int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    int sum=0;
    for(int i=1;i<=n;i++)
        cin>>c[i];
    for(int i=1;i<=n;i++)
        cin>>d[i];
    for(int i=1;i<=n;i++){
        ll a,b;
        a=c[i];
        b=d[i];
        int sign=0;
        if(a<0){
            sign^=1;
            a=-a;
        }
        if(b<0){
            sign^=1;
            b=-b;
        }
        if(a==0){
            sum+=(b==0);
            continue;
        }
        if(b==0){
            m1[{0,0}]++;
        }
        int d=gcd(a,b);
        a/=d;
        b/=d;
        if(sign==0){
            sign=1;
        }
        else{
            sign=-1;
        }
        m1[{sign*b,a}]++;
    }
    int mx=0;
    for(auto tmp:m1){
        mx=max(mx,tmp.second);
    }
    mx+=sum;
    cout<<mx<<endl;
}
View Code

E题

考虑使用dp,数据范围也暗示了这一点,每个位置只有取和不取,不取直接由前面信息更新,而取一定是取最远的,所以二分求最远距离更新即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=5e5+10;
int a[N];
int f[5050][5050];
int main(){
    ios::sync_with_stdio(false);
    int n,k;
    cin>>n>>k;
    int i,j;
    for(i=1;i<=n;i++){
        cin>>a[i];
    }
    sort(a+1,a+1+n);
    a[0]=-0x3f3f3f3f;
    for(i=1;i<=n;i++){
        for(j=1;j<=k&&j<=i;j++){
            int l=0,r=i;
            while(l<r){
                int mid=l+r>>1;
                if(abs(a[i]-a[mid])<=5)
                    r=mid;
                else
                    l=mid+1;
            }
            f[i][j]=max(f[i-1][j],f[l-1][j-1]+(i-l+1));
        }
    }
    int ans=0;
    for(i=1;i<=k;i++)
        ans=max(ans,f[n][i]);
    cout<<ans<<endl;
}
View Code

F1题

显然的贪心思路,找到度最多的点选择,之后并查集把其他点取进来

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=5e5+10;
int n,m;
int in[N];
vector<int> num[N];
queue<int> q;
pll ans[N];
int st[N];
int p[N];
int find(int x){
    if(x!=p[x]){
        p[x]=find(p[x]);
    }
    return p[x];
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    int i;
    for(i=1;i<=n;i++)
        p[i]=i;
    for(i=1;i<=m;i++){
        int a,b;
        cin>>a>>b;
        in[a]++,in[b]++;
        num[a].push_back(b);
        num[b].push_back(a);
    }
    int mx=0,rt;
    for(i=1;i<=n;i++){
        if(in[i]>mx){
            mx=in[i];
            rt=i;
        }
    }
    int cnt=0;
    for(auto x:num[rt]){
        p[x]=rt;
        ans[++cnt]={x,rt};
        q.push(x);
    }
    while(q.size()){
        int t=q.front();
        q.pop();
        int i;
        for(auto x:num[t]){
            int pa=find(x);
            int pb=find(t);
            if(pa!=pb){
                p[pa]=pb;
                ans[++cnt]={x,t};
                q.push(x);
            }
        }
    }
    for(i=1;i<n;i++){
        cout<<ans[i].first<<" "<<ans[i].second<<endl;
    }
}
View Code

 F2题

这题和上一题的思路有些相同,上一题是找最多的点,但是这次我们指定了点数,不难想到,如果先不考虑和1相连的边,那么剩下来的就是一些连通块

而1点需要用D边联通这些连通块,无解情况就是连通块个数大于D,显然无解,还有就是1点的度小于D,那根本连不了D个边,还有一种无解情况是,1无法连通这些连通块

之后构造答案也是如此,先把连通块连好之后,其他用并查集直接维护生成树即可。这题我的代码比较复杂

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=2e5+10;
int n,m,d;
vector<int> g[N];
vector<int> num[N];
vector<pll> tmp;
vector<pll> nxt;
int vis[N];
int cnt=0;
int flag=0;
int p[N];
int id[N];
int st[N];
vector<pll> ans;
queue<int> q;
void dfs(int u,int fa){
    int i;
    num[cnt].push_back(u);
    id[u]=cnt;
    for(i=0;i<(int)g[u].size();i++){
        int j=g[u][i];
        if(j==fa||vis[j])
            continue;
        vis[j]=1;
        dfs(j,u);
    }
}
int find(int x){
    if(x!=p[x]){
        p[x]=find(p[x]);
    }
    return p[x];
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m>>d;
    int i;
    for(i=1;i<=n;i++){
        p[i]=i;
    }
    for(i=1;i<=m;i++){
        int a,b;
        cin>>a>>b;
        if(a==1||b==1){
            tmp.push_back({a,b});
            flag++;
            continue;
        }
        g[a].push_back(b);
        g[b].push_back(a);
    }
    for(i=2;i<=n;i++){
        if(!vis[i]){
            cnt++;
            vis[i]=1;
            dfs(i,-1);
        }
    }
    if(cnt>d||flag<d){
        cout<<"NO"<<endl;
        return 0;
    }
    for(auto x:tmp){
        int a=x.first;
        int b=x.second;
        if(a>b)
            swap(a,b);
        if(st[id[b]]){
            nxt.push_back({a,b});
            continue;
        }
        d--;
        st[id[b]]=1;
        int pa=find(a);
        int pb=find(b);
        p[pb]=pa;
        ans.push_back({a,b});
        q.push(b);
    }
    for(i=1;i<=cnt;i++){
        if(!st[i]){
            cout<<"NO"<<endl;
            return 0;
        }
    }
    for(auto x:nxt){
        if(!d)
            break;
        int a=x.first;
        int b=x.second;
        if(a>b)
            swap(a,b);
        int pa=find(a);
        int pb=find(b);
        p[pb]=pa;
        ans.push_back({a,b});
        q.push(b);
        d--;
    }
    while(q.size()){
        auto t=q.front();
        q.pop();
        for(auto x:g[t]){
            int pa=find(x);
            int pb=find(t);
            if(pa!=pb){
                ans.push_back({t,x});
                p[pa]=pb;
                q.push(x);
            }
        }
    }
    cout<<"YES"<<endl;
    for(auto x:ans){
        cout<<x.first<<" "<<x.second<<endl;
    }
}
View Code

 

posted @ 2020-12-14 23:56  朝暮不思  阅读(87)  评论(0编辑  收藏  举报