Gym - 102220B Balanced Diet

    科技2022-07-31  118

    题目链接:https://codeforces.com/gym/102220/problem/B

    说题解之前,因为TL很多次,说说cin的加速和scanf。

    std::ios::sync_with_stdio(0);

    来加速cin 与cout ,这样cin的速度就和sanf差不多了,

    注意,这两个代码的头文件是 iostream

    并且如果用了这两个,就不要用scanf ,getchar,gets,fgets,fscanf了,

    他的作用是关于 iostream和stdio的同步,让c++和c的输入出不在挂钩了(具体原理我也不清楚哈)

    还有就是,用“\n”而不是 endl,也可以提高速度。

    题目大意

    自己好菜呀!这个题意读了好久才明白。先是给你一个数 T 有T组数据! 每组数据 给了 N和M表示有M种类型的糖果,这些糖果一共N个。 接下了是 M 组数据,表示如果你选第 i 中糖果,那么你最少选 Li (你也可以不选), 再接下来就是 N 行数据,每一行 ai 和 bi 表示这个糖果属于 bi 这个种类的,它的价值是ai。 最后让你输出你挑选的糖果的总价值除以 你取得糖果中数量最多的那种糖果的数量,然后化成最简分数, 比如说 第 1 种你取了 2 个,第 2 中你取了 4 个,第三种你取了 1 个,那么分母就是 4 了。

    解题思路

    相比读题的苦苦挣扎,解题就好受多了,既然我们要选出的分数最大,那么我们就可以直接暴力的去比较,从最多选一个,然后两个,这样我们遍历一遍就好了,从前向后开始遍历的时候,我们可以提前预处理一下,将每种没类型的的糖果的价值从大到小进行排序,然后遍历到几选的时候就可以直接选了前几个就行了,用一个vector数组,进行储存选几的时候sum和是多少。(注意我们不能直接找出最多要选的数量,然后每种都选前 相应 的数量的价值数,因为可能这种类型的糖果我们可以不选)说的有点复杂还是直接看代码吧!

    附带两份代码

    #include<bits/stdc++.h> using namespace std; typedef long long ll; vector<int>ve[100009],vec[100009]; int a[100009]; bool cmp(int x,int y) { return x>y; } int main() { int t,n,m,x,y; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d",&a[i]); for(int i=0;i<n;i++) { scanf("%d%d",&x,&y); ve[y].push_back(x); } for(int i=1;i<=m;i++){ sort(ve[i].begin(),ve[i].end(),cmp); for(int j=0;j<ve[i].size();j++){ vec[max((j+1),a[i])].push_back(ve[i][j]); } ve[i].clear(); } ll S=0,C=1,s=0,c; for(int i=1;i<=n;i++){ c=i; for(int j=0;j<vec[i].size();j++){ s+=vec[i][j]; } if(S*c<s*C){ S=s; C=c; } vec[i].clear(); } ll k=__gcd(S,C); printf("%lld/%lld\n",S/k,C/k); } return 0; }
    #include<bits/stdc++.h> using namespace std; typedef long long ll; vector<int>ve[100009],vec[100009]; int a[100009]; bool cmp(int x,int y) { return x>y; } int main() { ios::sync_with_stdio(0); int x,y,t,n,m; cin>>t; while(t--) { cin>>n>>m; for(int i=1;i<=m;i++) cin>>a[i];//第i种类型如果要取得话最少取多少 for(int i=0;i<n;i++) cin>>x>>y,ve[y].push_back(x); for(int i=1;i<=m;i++) { sort(ve[i].begin(),ve[i].end(),cmp);//排序 for(int j=0;j<ve[i].size();j++) { vec[max((j+1),a[i])].push_back(ve[i][j]);//构建前缀数组 因为你如果选的话,最少选 a【i】个数, // 所以让前a【i】个价值都放到选a【i】 这种情况,后面的就放入对应的位置 } ve[i].clear(); } ll ms=0,mc=1,ns=0,nc;//注意这里要用long long 不然第 2 组会爆 int for(int i=1;i<=n;i++) { nc=i; for(int j=0;j<vec[i].size();j++){ ns+=vec[i][j];//累计前 i 项的和 } if(ms*nc<ns*mc) ms=ns,mc=nc;//取最大的一组解 vec[i].clear(); } ll k=__gcd(ms,mc); cout<<ms/k<<"/"<<mc/k<<endl; } return 0; }
    Processed: 0.010, SQL: 8