easy题目链接
题目思路
emmm,题目的意思比赛的时候没怎么读懂。注意:题目的重新编排就是指换位置
其实题目很简单
我们只需知道数的个数之和sum和最多的数出现的次数ma
如果 ma <= sum/2 那么结果就是sum
如果 ma> sum/2 结果就是 2*(sum-ma)
由于a[i]的范围要用map
代码
#include<cstdio>
#include<algorithm>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n,rep,d,x,sum,ma=-1,ans;
map<int,int> a;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d %d",&rep,&d);
sum+=rep*d;
for(int i=1;i<=d;i++){
scanf("%d",&x);
a[x]+=rep;
}
}
map<int,int>::iterator ite;
for(ite=a.begin();ite!=a.end();ite++){
ma=max(ma,ite->second);
}
if(ma<=sum/2){
ans=sum;
}else{
ans=2*(sum-ma);
}
printf("%d\n",ans);
return 0;
}
hard题目链接
题目思路
数据范围变大了,就会tle,显然是要去掉map,
1:我自己想了一种方法,类似于hash把1-1e9的数据映射到1-1e7里面,双hash一下,直接把base当作10,因为如果要重新计算base也会超时,但是我觉得很容易被卡,不到万不得已的时候最好不要用,我觉得这样hash最好3重hash以上比较保险,但是我双hash也过了。
2:就是用结构体存下每个数的数值,及其重复的次数,然后我们排个序,将相同数值的重复次数全部加起来取最大值就完事了,我用的是pair
hash
#include<cstdio>
#include<algorithm>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=1e7+5;
const int mod1=9999991,mod2=9999973;
int n,rep,d,x;
ll sum,ma=-1,ans;
ll a[maxn],b[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d %d",&rep,&d);
sum+=rep*d;
for(int i=1;i<=d;i++){
scanf("%d",&x);
a[(x%mod1)]+=rep;
b[(x%mod2)]+=rep;
ma=max(ma,min(a[x%mod1],b[x%mod2]));
}
}
if(ma<=sum/2){
ans=sum;
}else{
ans=2*(sum-ma);
}
printf("%lld\n",ans);
return 0;
}
排序
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=4e6+5;
int n,len,rep,cnt;
ll sum,ma,temp;
pair<int,int> x[maxn];
int main(){
scanf("%d",&n);
while(n--){
scanf("%d%d",&rep,&len);
for(int i=1;i<=len;i++){
scanf("%d",&x[++cnt].first);
x[cnt].second=rep;
}
sum+=rep*len;
}
sort(x+1,x+1+cnt);
for(int i=1;i<=cnt;i++){
if(x[i].first==x[i-1].first){
temp+=x[i].second;
}else{
ma=max(ma,temp);
temp=x[i].second;
}
}
ma=max(ma,temp);//最后一次
if(ma<=sum/2){
printf("%lld\n",sum);
}else{
printf("%lld\n",2*(sum-ma));
}
return 0;
}