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); }
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); }
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); }
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); }
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); }
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); }
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); }