P4531[CTSC2005]魔术眼镜盒
考虑两个比较好想贪心。
$ 1. $ 既然要数量最大,优先从小选的比较优 。
$ 2. $ 两个比较大小接近的放在一起比较优 。
现将原数组排序。
手玩几组样例发现,为了满足贪心原则 $ 1 , 2 $ ,最后的答案肯定是从 $ 1 $ 开始的连续一段。
可以考虑枚举连续一段的端点,判定是否合法即可。
复杂度 $ O(n^2) $ ,实际远远达不到。
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int rd(){
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
vector<int> s1,s2;
int Ans_cnt,Now_s;
int n,m,s,num;
signed main()
{
// s1.resize(55000);
// s2.resize(55000);
// freopen("7.in","r",stdin);
// freopen("Ans.out","w",stdout);
n=rd();
m=rd();
s=rd();
for(int i=1;i<=n;i++)
{
int a;
a=rd();
s1.push_back(a);
}
for(int i=1;i<=m;i++)
{
int a;
a=rd();
s2.push_back(a);
}
if(s1.size()<s2.size()) s1.swap(s2);
sort(s1.begin(),s1.end());
sort(s2.begin(),s2.end());
int sum=0;
for(vector<int>::iterator it=s1.begin();it!=s1.end();it++)
{
int cnt=num;
int Maxn=0,xuan;
if(it==s1.end()) continue;
vector<int>::iterator it1=it;
vector<int>::iterator it2=s2.begin();
int now_sum=sum;
while(1)
{
Maxn=max(*it1,*it2);
if((now_sum+Maxn)*Maxn>s) break;
xuan=Maxn;
now_sum+=Maxn;
cnt+=2;
it1++;
it2++;
if(it1==s1.end()||it2==s2.end()) break;
}
if(cnt>Ans_cnt)
{
Now_s=xuan*now_sum;
Ans_cnt=cnt;
}
else if(cnt==Ans_cnt)
{
Now_s=min(Now_s,xuan*now_sum);
}
sum+=*it;
num++;
if(sum*Maxn>s||it1==s1.end()) break;
}
cout<<Ans_cnt<<" "<<Now_s<<endl;
}