Codeforces Round #574 (Div. 2)
A - Drinks Choosing
题意:
有n个学生,已知他们各自喜欢的饮料的编号(1~k), 有n/2(向上取整)份饮料,一份可以满足一个或两个相同的饮料需求。
问最多能满足多少个学生的需求。
分析:
思维题。将每种饮料的需求个数计数。一份可以满足一个或两个相同的饮料需求,则为了使每一份饮料发挥最大作用(不被浪费),就尽量先满足需求为偶数个的饮料需求,然后再考虑奇数。
代码:
#include<algorithm>
#include<cstdio>
#include<iostream>
#include<stdlib.h>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
int n,k;
int main(){ //有些混乱
ios::sync_with_stdio(false);
cin>>n>>k;
int a[k+1];
int num;
int m=(n+1)/2;
memset(a,0,sizeof(a));
for(int i=0;i<n;i++){
cin>>num;
a[num]++;
// cout<<" "<<a[num]<<endl;
}
int flag=0,ans=0;
for(int i=1;i<=k;i++){
// cout<<a[i]<<endl;
if(a[i]%2==0){
if(m-a[i]/2>0){
ans+=a[i];
m=m-a[i]/2;
}
else{
ans+=m*2;
m=0;
break;
}
}
}
for(int i=1;i<=k;i++){
if(m==0) break;
if(a[i]%2!=0){
if(m-a[i]/2>0){
ans+=a[i]-1;
m=m-a[i]/2;
}
else{
ans+=m*2;
m=0;
break;
}
}
}
if(m!=0) ans+=m;
cout<<ans<<endl;
return 0;
}
//int n, k, num; //看到的比较简单思路清晰的做法
// map<int,int>mp;
//int main(){
// ios::sync_with_stdio(false);
// cin>>n>>k;
// for(int i=0; i<n; i++){
// cin >>num;
// mp[num]++;
// }
// int a=0,b=0,ans=0;
// for(auto it: mp){
// b+=it.second%2;
// a+=it.second/2*2;
// }
// ans=a+(b+1)/2;
// cout << ans << endl;
// return 0;
//}
B - Sport Mafia
题意:
有一个空盒,可以里面放糖果,依次递增的放糖(eg:第一次放1颗,下一次放2颗…第n次放n颗); 也可以从里面取糖果,但是一次只能取1颗。
n次操作使盒子里的糖果变为k颗,问最多可以取多少次糖果。
分析:
二分。设最多取x次,则有线性关系:((n-x+1)(n-x))/2-x=k,
方程化简:x*x-(2*n+3)*x+n*n+n=2*k,
易得:x*x-2*n*x-x,在(-∞,-b/2*a],即在(-∞,n+3/2]单调递减
x的取值区间为[0,n-1],单调递减,所以用二分可解。
二分缩小区间,确定答案。
代码:
#include<algorithm>
#include<cstdio>
#include<iostream>
#include<stdlib.h>
#include<cstring>
using namespace std;
typedef long long ll;
ll k,n;
ll check(ll x)
{
return x*x-(2*n+3)*x+n*n+n;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
ll l=0,r=n-1,m;
while(l<=r)
{
m=(l+r)/2;
if(check(m)==2*k)
{
cout<<m<<endl;
break;
}
else if(check(m)<2*k) r=m-1;
else l=m+1;
}
return 0;
}
C - Permutation Minimization by Deque
题意:
输入两行n列个数,从中选取若干个数,所选的数不能相邻(上下左右为相邻),求所选的数和的最大值。
分析:
dp。状态转移方程为:
dp[0][i]=max( dp[0][i] , dp[1][i-1]+a[i] )
dp[1][i]=max( dp[1][i] , dp[0][i-1]+b[i] )
代码:
#include<algorithm>
#include<cstdio>
#include<iostream>
#include<stdlib.h>
#include<cstring>
using namespace std;
typedef long long ll;
ll dp[2][100005];
ll a[100005],b[100005];
ll n;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
for(int i=0;i<n;i++)
cin>>b[i];
dp[0][0]=a[0];
dp[1][0]=b[0];
for(int i=1;i<n;i++)
{
dp[0][i]=max(dp[0][i-1],dp[1][i-1]+a[i]);
dp[1][i]=max(dp[1][i-1],dp[0][i-1]+b[i]);
}
ll ans=max(dp[0][n-1],dp[1][n-1]);
cout<<ans<<endl;
return 0;
}