Codeforces Round #544 (Div. 3)

A. Middle of the Contest

题目大意:给你(HH,MM)形式的两个时间点,它们之间相差偶数分钟,问中间时刻是多少?

题目思路:计算两个时间点间有多少分钟,除2后加到起始时间上,注意分钟达到60时,时钟需要进位。

AC代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int h1,h2,m1,m2,h3,m3;
    scanf("%d:%d",&h1,&m1);
    scanf("%d:%d",&h2,&m2);
    int tot=(h2-h1)*60+(m2-m1);
    tot/=2;
    h3=h1+tot/60;
    m3=m1+tot%60;
    h3+=m3/60;
    m3%=60;
    if(h3<10) printf("0%d:",h3);
    else printf("%d:",h3);
     if(m3<10) printf("0%d\n",m3);
    else printf("%d\n",m3);
    return 0;
 } 

B. Preparation for International Women's Day

题目大意:告诉你n个礼物,每个礼物中有di个糖果,礼物两两组合为一个盒子。要求盒子内糖果数为k的倍数。问最多可以装多少个符合条件的盒子?

题目思路:直接枚举明显超时O(n2),可以考虑先将每个礼物对k取余,再记录取余得到的结果的出现次数,最后枚举一遍,计算拼凑出和为k的情况数。注意单独计算取余结果为0的礼物自己互相组合形成盒子。

AC代码:

#include<bits/stdc++.h>
using namespace std;
int t[105];
bool vis[105];
int main()
{
    int n,k;
    cin>>n>>k;
    memset(t,0,sizeof(t));
    int tmp;
    for(int i=1;i<=n;i++)
    {
        cin>>tmp;
        t[tmp%k]++;
    }
    int ans=0;
    ans+=t[0]/2;
    vis[0]=true;
    for(int i=1;i<k;i++)
    {
        if(vis[i]) continue;
        if(k-i==i) ans+=t[i]/2;
        else ans+=min(t[i],t[k-i]);
        vis[i]=true;
        vis[k-i]=true;
    }
    cout<<ans*2<<endl;
    return 0;
 } 

C. Balanced Team

题目大意:告诉你n个数,定义一个合法的集合为:集合中元素的最大值与最小值的差值不超过5,问由这n个数形成的合法集合的大小最大为多少?

题目思路:先将n个数排序,再枚举所有元素,维护一个最大值与最小值之差不超过5的队列,更新队列长度最大值。O(n*log(n))

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=200005;
#define ll long long
queue<ll> que;
ll a[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    sort(a+1,a+n+1);
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        while(que.size()&&a[i]-que.front()>5) que.pop();
        que.push(a[i]);
        if(ans<que.size()) ans=que.size();
    } 
    cout<<ans<<endl;
    return 0;
 } 

D. Zero Quantity Maximization

题目大意:有两个集合,分别为A和B,其中各有n个元素。现在定义C集合:其中每个元素ci=d*ai+bi,d可取任意值,问当d取最优时,C集合中0元素最多为多少?

题目思路:令(ai,bi)为一数对,数对有四种类型:①.(0,0)②(0,y)③(x,0)④(x,y)   

对于第一种类型,d取任意值,对应的ci都是0,所以计算它的数量,加到最终答案里。

对于第二种类型,d取任意值,对应的ci都不可能是0,所以忽略它的存在。

对于第三种类型,只有d取0时,对应的ci才是0,所以对这一类单独计数,更新ans

对于第四种类型,利用gcd把它化成最简形式(x,y互质),用STL中的map记录不同最简数对的数量,更新ans

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=200005;
int a[maxn],b[maxn];
struct node{
    int a,b;
    node(){}
    node(int a,int b):a(a),b(b){}
    bool operator<(const node&other) const{
        if(a==other.a) return b<other.b;
        return a<other.a;
    }
};
map<node,int> m1;
int gcd(int a,int b) {
    return b==0?a:gcd(b,a%b);
}
int main()
{
    int n,ans=0;
    scanf("%d",&n); 
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&b[i]);
    int x=0,add=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]==0&&b[i]==0) add++;
        else if(a[i]==0) continue;
        else if(b[i]==0) x++,ans=max(ans,x);
        else 
        {
            int k=gcd(a[i],b[i]);
            int tmp=++m1[node(a[i]/k,b[i]/k)];
            ans=max(ans,tmp);
        }
    }
    printf("%d\n",ans+add);
    return 0;
} 

E. K Balanced Teams

待更新

F1. Spanning Tree with Maximum Degree

题目大意:给你一个无向图,求任意一个生成树,要求其上度数最大的点的度数,尽可能大。

题目思路:先计算所有点的度数,把度数最大的点以及其所连着的边加入正在构造的生成树,再添加边集中其它的边来构造生成树。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define maxn 200005

int n,m; 
int fa[maxn];
int d[maxn];

Init_DisjointSet()
{
    for(int i=1;i<=m;i++)
        fa[i]=i; 
} 
int find(int k)    {return fa[k]==k?k:fa[k]=find(fa[k]);}
 
struct Edge{
    int s,t;
}edge[maxn];  

bool vis[maxn]; 
 
void work(int size)
{
    int k1,k2;
    int cnt=0; 
    for(int j=1;j<=m;j++)
    {
        Edge tmp=edge[j];
        if(vis[j]) continue; 
        int k1=find(tmp.s);    
        int k2=find(tmp.t);
        if(k1!=k2) 
        {
            fa[k2]=k1;
            vis[j]=1;    
            cnt++;
            if(cnt==size) return;
        }
    }
}

int main()
{
    int s,t;
    scanf("%d%d",&n,&m);
    memset(d,0,sizeof(d));
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&s,&t);
        edge[i].s=s;
        edge[i].t=t;
        d[s]++;
        d[t]++;
    }
    int p,maxd=0;
    for(int i=1;i<=n;i++)
    {
        if(maxd<d[i])
        {
            p=i;
            maxd=d[i];
         } 
    }
    memset(vis,0,sizeof(vis)); 
    Init_DisjointSet(); 
    for(int i=1;i<=m;i++)
    {
        s=edge[i].s;
        t=edge[i].t;
        if(s==p||t==p) 
        {
            vis[i]=true;
            int k1=find(s);    
            int k2=find(t);
            fa[k2]=k1;
        }
    }    
    work(n-1-maxd); 
    for(int i=1;i<=m;i++)  
        if(vis[i])
            printf("%d %d\n",edge[i].s,edge[i].t);
    return 0;
} 

F2. Spanning Tree with One Fixed Degree

待更新

猜你喜欢

转载自www.cnblogs.com/Andrew-aq/p/10499434.html