集训队选拔赛 lonely_wind的传说(eazy+hard)(思维)

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值