A
思路
做法显然,但是需要注意一些小的细节:
①不能输出如"2:2"这样的时间,必须输出"02:02"这样的时间;
②中间的冒号是":",而不是“:”。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int a,b,c,d,n1,n2,n,aa,bb;
char x;
signed main()
{
cin>>a>>x>>b>>c>>x>>d;
n1=a*60+b;
n2=c*60+d;
n=(n1+n2)/2;
aa=n/60,bb=n%60;
if (aa<10) cout<<0<<aa;
else cout<<aa;
cout<<x;
if (bb<10) cout<<0<<bb;
else cout<<bb<<endl;
return 0;
}
B
思路
用一个桶, 记录下除以 余 的数的数量。
显然,若 是 的倍数,那么可以送给同一个Polycarp女友的盒子对就可以配成 组,即可配成 个盒子。
所以,直接枚举 ,并求出 使得 为 的倍数,最后用上面所说的方法求一下就可以啦。注意特判一下 的情况,可能配成 个盒子。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,k,ans;
int a[200005],b[105];
signed main()
{
cin>>n>>k;
for (int i=1;i<=n;i++) cin>>a[i];
for (int i=1;i<=n;i++) b[a[i]%k]++;
for (int i=0;i<=k/2;i++)
{
int o=(k-i)%k;
if (i==o) ans+=(b[i]/2)*2;
else ans+=min(b[i],b[o])*2;
}
cout<<ans<<endl;
return 0;
}
C
思路
暴力找显然会超时。
那么怎么办呢?首先按升序排序。然后,对于每个 向后找最后一个与 之差不大于5的数的位置;记这个位置为 ,那么就能形成人数为 的BT(Balanced Team)。
注意"向后找最后一个与 之差不大于5的数的位置"可以用二分来完成。
其时间复杂度为 ,不会超时。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,ans=-1,last;
int a[200005];
int find(int l,int r,int k)
{
if (l+1==r||l==r)
{
if (a[r]-k>5) return last;
else return max(r,last);
}
int mid=(l+r)>>1;
if (a[mid]-k<=5)
{
last=mid;
return find(mid,r,k);
}
else return find(l,mid,k);
}
signed main()
{
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
for (int i=1;i<=n;i++) last=-1,ans=max(ans,find(i,n,a[i])-i+1);
cout<<ans<<endl;
return 0;
}
D
好惨啊~WA了7次
思路
首先,观察这个式子: 。
将 带入,得
所以,对于每个 求出满足要求的 ;最后数一数最后有多少个不同的 即可。
这么简单?
怎么可能!
①哇哇!RE!
显然,当
且
时,是不存在
的,这种情况直接舍去;
另外,当
时,
可以随便取值;假设这种情况有
个,并暂时忽略这种情况,最后将答案加上
就是最终的答案。
②哇哇!WA!
您的精度出现了问题。
如何控制精度呢?我们可以将分子与分母约分后用map存下。记录下每对约分后分子与分母的相同对数并加上
就是最终的答案。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,ans=-1,last;
int a[200005];
int find(int l,int r,int k)
{
if (l+1==r||l==r)
{
if (a[r]-k>5) return last;
else return max(r,last);
}
int mid=(l+r)>>1;
if (a[mid]-k<=5)
{
last=mid;
return find(mid,r,k);
}
else return find(l,mid,k);
}
signed main()
{
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
for (int i=1;i<=n;i++) last=-1,ans=max(ans,find(i,n,a[i])-i+1);
cout<<ans<<endl;
return 0;
}
E
思路
一道略简单的 题。
状态设计 表示,目前看到 这个人,分 个队时最多能进队的人数。
状态转移显然;设 为 之前最前一个与 之差不大于 的数的位置。那么, 可以贪心地与 分在一组也可以哪个组都不去。
第一种情况:哪个组都不去。继承上一个状态: 。
第二种情况:与
分在一组。显然,位置在
到
的位置均要贪心地选。并且,看到
的时候必须贪心地选
组,不能选
组,否则
根本进不来,原因是含有
的第
组中一定会有与
之差大于5的数。
所以,此时
。
综上所述,状态转移就是:
注意,我们不需要用二分找 ,朴素找也会超时。总时间复杂度为 。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=505;
int n,m,ans=-1;
int a[maxn],dp[maxn][maxn];
signed main()
{
cin>>n>>m;
for (int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
dp[1][1]=1;
for (int i=1;i<=n;i++)
{
int last=i;
while (abs(a[last]-a[i])<=5&&last>=1) last--;
for (int j=1;j<=m;j++) dp[i][j]=max(dp[i-1][j],dp[last][j-1]+(i-last));
}
for (int i=1;i<=m;i++) ans=max(ans,dp[n][i]);
cout<<ans<<endl;
return 0;
}
F1
唉,心态真TM炸了,比赛的时候绞尽脑汁就是想不出来;比赛后仍然想不出来,重新看题才发现本菜鸡把题目看错了。
唉,差一点就进前 了QAQ
题面(罚自己写)
给定一个无向联通图,请找出它的一个生成树使得该树中所有节点的度数的最大值最大,并输出该树的所有边。
思路
显然,我们要贪心地取那个原图中度数最大的节点与其所有边。然后,在保证选出来的是一棵树的情况下,每次任意加边。
注意判断其是否为树(即无环)可以用并查集来完成。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,m,u,v,maxv=-1,pos;
int de[200005],father[200005];
struct edge
{
int u,v;
}e[400005];
int find(int x)
{
if (x!=father[x]) father[x]=find(father[x]);
return father[x];
}
signed main()
{
cin>>n>>m;
for (int i=1;i<=n;i++) father[i]=i;
for (int i=1;i<=m;i++)
{
cin>>e[i].u>>e[i].v;
de[e[i].u]++,de[e[i].v]++;
}
for (int i=1;i<=n;i++)
{
if (de[i]>maxv)
{
maxv=de[i];
pos=i;
}
}
for (int i=1;i<=m;i++)
{
if (e[i].u==pos||e[i].v==pos)
{
cout<<e[i].u<<' '<<e[i].v<<endl;
father[find(e[i].v)]=find(e[i].u);
}
}
for (int i=1;i<=m;i++)
{
if (find(e[i].u)!=find(e[i].v)&&e[i].u!=pos&&e[i].v!=pos)
{
cout<<e[i].u<<' '<<e[i].v<<endl;
father[find(e[i].v)]=find(e[i].u);
}
}
return 0;
}
E2
做不出来咕咕咕~
总结
①并查集三个月没做了~这一次又巩固了一遍;
②动规
增强了一丢丢;
③信心加了一点点。