CF1133A~F

A.MOC

给出两个时间,算中位数的时间。

#include<bits/stdc++.h>
using namespace std;
int h1,m1,h2,m2;
int main () {
    scanf("%d:%d",&h1,&m1);
    scanf("%d:%d",&h2,&m2);
    printf("%02d:%02d\n",(h1*60+m1+h2*60+m2)/120,(h1*60+m1+h2*60+m2)/2%60); 
} 
View Code

 

B.PIWD

给出一个序列,当两个数的和是k的倍数的时候,可以作为一组被取出。询问最多取出多少组。

开一个长度为k的数组存放每种数的出现次数,两个模k的值相同的数是一种数,最后遍历一遍数组就可以。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int a[maxn];
int cnt[maxn];
int n,k;
int main () {
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=n;i++) cnt[a[i]%k]++;
    //for (int i=0;i<k;i++) printf("%d ",cnt[i]);
    int ans=0;
    for (int i=1;i<k;i++) {
        if (i==k-i) {
            int tt=cnt[i];
            ans+=tt/2;
            cnt[i]=0;
            continue;
        }
        int tt=min(cnt[i],cnt[k-i]);
        ans+=tt;
        cnt[i]-=tt;
        cnt[k-i]-=tt;
    }
    ans+=cnt[0]/2;
    ans*=2;
    printf("%d\n",ans);
}
View Code

 

C.BT

给出一个序列,在这个序列里找一些数,使得最大值和最小值的差小于等于5。询问最多能选出多少数。

先对序列排序,然后二分答案。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int a[maxn];
int n;
int main () {
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    int Max=0;
    for (int i=1;i<=n;i++) {
        int j=upper_bound(a+1,a+n+1,a[i]+5)-a;
        Max=max(Max,j-i);
    }
    printf("%d\n",Max);
}
View Code

 

D.ZQM

给出两个个序列,可以将选择一个固定的比值,使得第一个序列里的所有数乘这个比值加上第二个序列里的数是0,询问最多变多少个0。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int a[maxn];
int b[maxn];
int n;
map<long double,int> pos;
long double c[maxn];
int main () {
    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 wjm=0,Max;
    for (int i=1;i<=n;i++) {
        if (b[i]==0&&a[i]==0) wjm++;
        else if (b[i]==0)
            pos[0]++;
        else if (a[i]!=0) {
            c[i]=b[i]*1.0/a[i];
            pos[c[i]]++;
        }
        Max=max(Max,pos[c[i]]);
    }
    printf("%d\n",Max+wjm);
} 
View Code

 

E.KBT

可以选k组人,每组人里的最大值和最小值的差小于等于5,询问最大总人数。

先预处理出每个人作为组里最小的人的时候可以选的范围,然后根据这个范围二维DP。

#include<bits/stdc++.h>
using namespace std;
const int maxn=5005;
int a[maxn];
int dp[maxn][maxn];
int wjm[maxn];
int n,k; 
int main () {
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    for (int i=1;i<=n;i++) wjm[i]=upper_bound(a+i,a+1+n,a[i]+5)-a;
    int ans=0;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=k;j++)
            {
                dp[wjm[i]][j]=max(dp[wjm[i]][j],dp[i][j-1]+wjm[i]-i);
                dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
                ans=max(ans,dp[wjm[i]][j]);
                ans=max(ans,dp[i+1][j]);
            }
    printf("%d\n",ans);
}
View Code

 

F1.STMD

构建单点度数最大的生成树

考虑到最小生成树只会删边,所以直接找到当前度数最大的点,围绕这个点建树即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
struct node {
    int u,v;
}edge[maxn];
int father[maxn];
int findfather (int x) {
    int a=x;
    while (x!=father[x]) x=father[x];
    while (a!=father[a]) {
        int z=a;
        a=father[a];
        father[z]=x;
    } 
    return x;
}
vector<node> ans;
int inDegree[maxn];
int wjm=0;
int n,m;
int main () {
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) father[i]=i;
    for (int i=1;i<=m;i++) {
        scanf("%d%d",&edge[i].u,&edge[i].v);
        inDegree[edge[i].u]++;
        inDegree[edge[i].v]++;
    }
    int u=-1,Max=0;
    for (int i=1;i<=n;i++) {
        if (inDegree[i]>Max) {
            Max=inDegree[i];
            u=i;
        }
    }
    for (int i=1;i<=m;i++) {
        if (edge[i].u==u||edge[i].v==u) {
            ans.push_back(edge[i]);
            int faU=findfather(edge[i].u);
            int faV=findfather(edge[i].v);
            father[faU]=faV;
        }
    } 
    for (int i=1;i<=m;i++) {
        int faU=findfather(edge[i].u);
        int faV=findfather(edge[i].v);
        if (faU!=faV) {
            ans.push_back(edge[i]);
            father[faU]=faV;
        }
    } 
    for (int i=0;i<ans.size();i++) printf("%d %d\n",ans[i].u,ans[i].v);
}
View Code

 

F2.STOFD

询问是否能构建生成树,使得点1的度数恰好为k。

先枚举与点1相连的所有点,如果这些点之间除了点1还有别的边相连,就把他们分成一组,这样会有一个个连通块。如果k的值大于1的初始度数或小于连通块的个数,自然就无解,下面考虑有解的情况。

对于每个连通块,取出一个点与1连接,如果边数还不够,就再取出点与1连接,最后把已经与1连接的点设为已访问做第二遍DFS。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int n,m,k;
vector<int> g[maxn];
int visit[maxn];
vector<int> wjm[maxn];
void dfs (int u,int cnt) {
    visit[u]=1;
    for (int v:g[u]) {
        if (v==1) {
            wjm[cnt].push_back(u);
            continue;
        }
        if (visit[v]) continue;
        dfs(v,cnt);
    }
}
void dfs_ (int u) {
    visit[u]=1;
    for (int v:g[u]) {
        if (visit[v]) continue;
        printf("%d %d\n",u,v);
        dfs_(v);
    }
}
int main () {
    scanf("%d%d%d",&n,&m,&k);
    for (int i=0;i<m;i++) {
        int x,y;
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x); 
    }
    int v,cnt=0;
    for (auto v:g[1]) {
        if (!visit[v]) {
            dfs(v,cnt);
            cnt++;
        }
    }
    if (k>g[1].size()||k<cnt) {
        printf("NO\n");
        return 0;
    }
    printf("YES\n");
    memset(visit,0,sizeof(visit));
    visit[1]=1;
    int cnt_=cnt;
    for (int i=0;i<cnt;i++) {
        int v=wjm[i][0];
        printf("1 %d\n",v);
        visit[v]=1;
    }
    for (int i=0;i<cnt;i++) {
        if (cnt_==k) break;
        for (int j=1;j<wjm[i].size();j++) {
            if (cnt_==k) break;
            int v=wjm[i][j];
            printf("1 %d\n",v);
            visit[v]=1;
            cnt_++;
        }
    }
    for (int i=2;i<=n;i++) if (visit[i]) dfs_(i);
}
View Code

 

posted @ 2020-07-17 19:20  zlc0405  阅读(218)  评论(0编辑  收藏  举报