这次div3 虽然打得不是很好,但不过不是很难,都是很基础。
http://codeforces.com/contest/1133
A. Middle of the Contest
题意:给你两个时间,要求你输出两个时间的中点,这道题最简单的办法就是,吧时间全部转换为分,然后再转换为题目要求的表达,下面的代码没有用这种方法,写得有点臃肿。
#include<bits/stdc++.h>
using namespace std;
#define iofast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N=2e5+10;
typedef long long ll;
int main()
{
///iofast;
int a,b,c,d;
scanf("%d:%d",&a,&b);
scanf("%d:%d",&c,&d);
if(a>c)
swap(a,c),swap(b,d);
int tmp=(c-a)*60+(d-b);
tmp=tmp/2;
int aa=tmp/60;
int bb=tmp%60;
a=a+aa;
b=b+bb;
while(b>=60)
a+=1,b-=60;
if(a<10)
cout<<"0"<<a;
else
cout<<a;
cout<<":";
if(b<10)
cout<<"0"<<b;
else
cout<<b;
cout<<endl;
return 0;
}
B. Preparation for International Women's Day
题意:给出n和k,接下来是n个数,问能从n个数中选出多少对数,其中每对数加起来能被k整除。
做法,每个数对k取模,并且记录下来个数,余数为i和k-i的数相加起来能被k整除。
#include<bits/stdc++.h>
using namespace std;
#define iofast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N=2e5+10;
typedef long long ll;
int a[N],n,k,b[N];
map<int,int>mp;
int main()
{
///iofast;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=a[i]%k;
mp[b[i]]++;
}
//sort(a+1,a+n+1);
int ans=mp[0]/2*2;
for(int i=1;i<k;i++)
{
if(i!=k-i)
{
int tmp=min(mp[i],mp[k-i]);
ans+=tmp*2;
mp[i]-=tmp;
mp[k-i]-=tmp;
}
else
{
int tmp=mp[i];
ans+=tmp/2*2;
mp[i]=tmp/2*2;
}
}
cout<<ans<<endl;
return 0;
}
C. Balanced Team
题意:在n个数中k个数出来,其中最大值和最小值相差不应该超过5,问k的最大值;
做法,排序,然后对每一个数a[i]找到第一个比a[i]+5大的数的位置;
#include<bits/stdc++.h>
using namespace std;
#define iofast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N=2e5+10;
typedef long long ll;
int a[N],n,k,b[N];
map<int,int>mp;
int main()
{
///iofast;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
a[n+1]=1e9+10;
int ans=1,tmp=1,mx=a[1],mr=1;
for(int i=1;i<=n;i++)
{
int k=upper_bound(a+i,a+n+2,a[i]+5)-(a+i);
//cout<<a[i+k]<<endl;
ans=max(ans,k);
}
cout<<ans<<endl;
return 0;
}
D. Zero Quantity Maximization
题意:给出两个数组,数组都大小为n,定义一个数组c c[i]=d*a[i]+b[i],问选取合适的d,使数组c中为0的个数最大,求这个最大值
做法,用map 标记 pair,pair 保存 -a[i]和b[i]的最简形式,要求一个gcd,然后找到最大值。
#include<bits/stdc++.h>
using namespace std;
#define iofast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N=2e5+10;
typedef long long ll;
int n,a[N],b[N];
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
///iofast;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
cin>>b[i];
}
map<pair<int,int>,int>mp;
int cnt=0;
pair<int,int> p1;
for(int i=1;i<=n;i++)
{
if(a[i]==0&&b[i]!=0)
continue;
else if(a[i]==0&&b[i]==0)
cnt++;
else if(a[i]!=0&&b[i]==0)
mp[make_pair(0,0)]++;
else
{
int x=gcd(a[i],b[i]);
p1.first=-b[i]/x;
p1.second=a[i]/x;
mp[p1]++;
}
}
map<pair<int,int>,int>::iterator it;
int ans=0;
for(it=mp.begin();it!=mp.end();it++)
{
ans=max(ans,it->second);
}
cout<<ans+cnt<<endl;
return 0;
}
E.K Balanced Teams
题意,给出n个数,和一个k,要求你从n个数中选出k组数,要求每组数的最大值和最小值相差不大于5.问最多能选多少个数。
这是一个dp题,dp[i][j]表示前i个人分为j组的最大值,当遇到第i个数时可以选取,可以要,如果要,m表示i后面比a[i]-5小的第一个数
dp[i][j]=max(dp[i-1][j],dp[m][j-1]+i-m);
#include<bits/stdc++.h>
using namespace std;
#define iofast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 2e5 + 10;
typedef long long ll;
int n, k, a[N], b[N];
int dp[5010][5010];
int main()
{
iofast;
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
if (k == n)
{
cout << n << endl;
return 0;
}
sort(a + 1, a + n + 1);
a[0] = -10;
memset(dp, 0, sizeof(dp));
int ans = 0;
for (int i = 1; i <= n; i++)
{
int m = i;
while (a[m] + 5 >= a[i])
{
m--;
}
for (int j = 1; j <= min(i, k); j++)
{
dp[i][j] = max(dp[i - 1][j], dp[m][j - 1] + i - m);
}
}
for(int i = 1;i <= k; i++)
ans = max(ans, dp[n][i]);
cout << ans << endl;
return 0;
}
F1. Spanning Tree with Maximum Degree
题目意思为,给出一个n个点,m条边的无向图,要求你求一颗所有顶点入度最大的生成树?
看了看样列猜了猜,直接写了一个找到入度最大的点然后开始BFS的代码居然过了??
#include<bits/stdc++.h>
using namespace std;
#define iofast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N=2e5+10;
typedef long long ll;
int n,m,a[N],b[N];
int in[N],vis[N];
vector<int>g[N];
void bfs(int x)
{
queue<int>qu;
vis[x]=1;
qu.push(x);
while(!qu.empty())
{
int u=qu.front();
qu.pop();
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(vis[v])
continue;
cout<<u<<" "<<v<<endl;
vis[v]=1;
qu.push(v);
}
}
}
int main()
{
memset(in,0,sizeof(in));
memset(vis,0,sizeof(vis));
cin>>n>>m;
int u,v;
for(int i=1;i<=m;i++)
{
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
in[u]++;
in[v]++;
}
int maxn=0,mx=0;
for(int i=1;i<=n;i++)
{
if(in[i]>maxn)
{
maxn=in[i];
mx=i;
}
}
bfs(mx);
return 0;
}
F2. Spanning Tree with One Fixed Degree
题目意思为,给出一个n个点,m条边的无向图,还有一个d,叫你找到一个 使标号为1的点的度数为d的生成树,或者不存在。
这道题错了很多次。
做法:先用dfs找到图中连通量的个数以及其中与1相连的点,如果大于d则不存在,然后吧与1相连的点加入,然后进行一个bfs,但不过要注意与1相连的边怎么加,需要一定的技巧,我在这里错了很多次。
#include<bits/stdc++.h>
using namespace std;
#define iofast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 2e5 + 10;
typedef long long ll;
vector<int>g[N];
int n,m,d,in[N],vis[N],tot;
int mr[N];
vector<int>one[N];
vector<int>ans1,ans2;
queue<int>qu;
void dfs(int u,int id)
{
vis[u]=1;
for(int i=0; i<g[u].size(); i++)
{
int v=g[u][i];
if(vis[v])
continue;
if(v==1)
{
one[id].push_back(u);
continue;
}
dfs(v,id);
}
}
void bfs()
{
while(!qu.empty())
{
int u=qu.front();
qu.pop();
for(int i=0; i<g[u].size(); i++)
{
int v=g[u][i];
if(vis[v])
continue;
vis[v]=1;
ans1.push_back(u);
ans2.push_back(v);
qu.push(v);
}
}
}
int main()
{
iofast;
memset(vis,0,sizeof(vis));
memset(in,0,sizeof(in));
memset(mr,0,sizeof(mr));
cin>>n>>m>>d;
int u,v;
for(int i=1; i<=m; i++)
{
cin>>u>>v;
in[u]++;
in[v]++;
g[u].push_back(v);
g[v].push_back(u);
}
int cnt=0;
tot=0;
if(in[1]<d)
{
cout<<"NO"<<endl;
return 0;
}
for(int i=2; i<=n; i++)
{
if(!vis[i])
{
tot++;
dfs(i,tot);
}
}
if(tot>d)
{
cout<<"NO"<<endl;
return 0;
}
memset(vis,0,sizeof(vis));
vis[1]=1;
for(int i=1; i<=tot; i++)
{
//cout<<one[i].size()<<endl;
v=one[i][0];
ans1.push_back(1);
ans2.push_back(v);
vis[v]=1;
qu.push(v);
cnt++;
}
for(int i=1; i<=tot&&cnt<d; i++)
{
for(int j=1; j<one[i].size()&&cnt<d; j++)
{
v=one[i][j];
ans1.push_back(1);
ans2.push_back(v);
vis[v]=1;
qu.push(v);
cnt++;
}
}
bfs();
cout<<"YES"<<endl;
for(int i=0; i<ans1.size(); i++)
{
cout<<ans1[i]<<" ";
cout<<ans2[i]<<endl;
}
return 0;
}