2018.8.7提高B组模拟考试

T1 题意简述:jzoj5461

解题思路:贪心。

考虑先用完k张优惠券,只需将商品按优惠价排序,依次判断钱是否足够,若是则ans++,否则直接退

出循环并输出ans即可。

k张优惠券用完后若钱还未用完,则考虑用前面商品的优惠券买后面的商品。注意要把未买的商品按

原价重新排序。只需把用了优惠券的商品的原价与优惠价之差价放进一个小根堆,每次判断:此商品

原价是否小于堆顶商品差价+此商品优惠价。若是则直接用原价买即可,否则用堆顶商品差价+此商品

优惠价买即可。注意有0张优惠券的情况,因此要特判队列是否为空,若是则直接用原价买即可。

由于本蒟蒻及ErkkiErkko大佬均认为把商品按原价重新排序的方法有误,故欢迎各位大佬前来Hack。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
ll n,k,m,ans;
priority_queue<ll,vector<ll>,greater<ll> > que;
struct uio{
    ll val,fre;
}war[50001];
bool cmp(uio x,uio y)
{
    if(x.fre==y.fre)
        return x.val<y.val;
    return x.fre<y.fre;
}
bool cmp1(uio x,uio y)
{
    return x.val<y.val;
}
int main()
{
    freopen("shopping.in","r",stdin);
    freopen("shopping.out","w",stdout);
    scanf("%lld%lld%lld",&n,&k,&m);
    for(ll i=1;i<=n;i++)
        scanf("%lld%lld",&war[i].val,&war[i].fre);
    sort(war+1,war+1+n,cmp);
    for(ll i=1;i<=k;i++)
    {
        que.push(war[i].val-war[i].fre);
        if(m>=war[i].fre) m-=war[i].fre,ans++;
    }
    sort(war+1+k,war+1+n,cmp1);
    for(ll i=k+1;i<=n;i++)
    {
        if(m>=war[i].val&&(que.empty()||que.top()>war[i].val-war[i].fre)) m-=war[i].val,ans++;
        else if(!que.empty()&&m>=war[i].fre+que.top()) m-=war[i].fre+que.top(),ans++,que.pop(),que.push(war[i].val-war[i].fre);
    }
    printf("%lld\n",ans);
    return 0;
}


T2 题意简述:jzoj5455

解题思路:

原文地址:https://www.cnblogs.com/water-radish/p/9439386.html

时间: 2024-11-02 08:03:47

2018.8.7提高B组模拟考试的相关文章

2018.8.6提高A组模拟考试

emmm看起来A组的题也没比B组难多少嘛... T1 题意简述:jzoj5796 解题思路:首先发现数字是输入数据中最特殊的字符,因此可以在找到数字后向四周dfs找到水箱边界. 其次发现题目中说“不会把水管分叉也不会出现水管交叉的情况”,因此可以在找到水箱后用dfs求 出每根水管的位置及其连接的水箱. 然后根据基本的物理原理(牛顿笑着躺下了)发现若同一水箱所连的两根水管所处位置高低不同,那 么在填满低水管所连的水箱之前,高水管所连的水箱是不会有水进入的. 综上,只需dfs一遍即可得出水箱灌满的次

2018.8.10提高B组模拟考试

为了迎合今天的讲课内容——数论,A组和B组都各出了两道数学. 对于完全不会数论的博主来说,这简直是灾难. T1 题意简述:jzoj5791 解题思路:看到这道题,首先想到对n个数分别分解成质数后存在数组里. 然后呢?枚举ans吗? 其实可以二分答案,加上一个求质数个数的技巧就能过. 发现cnt[2]=ans/2+ans/4+ans/8+... cnt[3]=ans/3+ans/9+ans/27+... 本题结束. #include<iostream> #include<cstdio>

2018.8.9提高B组模拟考试

今天连续3道题都出锅...无F♂A可说 T1 题意简述:jzoj5775 解题思路:还算简单... 考虑先暴力算出(1,1)的魔音值,然后递推. 发现 (x,y)->(x+1,y) 魔音值增加了1~x行中起始点的数量,减少了x+1~n行中起始点的数量. (x,y)->(x-1,y) 魔音值增加了x~n行中起始点的数量,减少了1~x-1行中起始点的数量. (x,y)->(x,y+1) 魔音值增加了1~y列中起始点的数量,减少了y+1~n列中起始点的数量. (x,y)->(x,y-1)

【NOIP2016提高A组模拟8.15】Password

题目 分析 首先我们知道,原A序列其实表示一个矩阵,而这个矩阵的对角线上的数字就是答案B序列. 接着\(a.b>=gcd(a,b)\),所以序列A中的最大的数就是ans[1],第二大的数就是ans[2]. 但是ans[3]并不一定就是序列A中的第三大的数,因为gcd(ans[1],ans[2])有可能是序列A中的第三大的数. 所以但找到了ans[i],对于每个gcd(ans[i],ans[1~i-1])在序列A中删掉两个(就是删掉2(i-1)个.为什么是两个自己考虑).时间复杂度\(O(n^2l

【NOIP2016提高A组模拟8.14】传送带

题目 在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段.两条传送带分别为线段AB和线段CD.FTD在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R.现在FTD想从A点走到D点,他想知道最少需要走多长时间 分析 易得,答案就是首先在AB上走一段,然后走到CD上的一点,再走到D. 正解就是三分套三分,但本人很懒,打了个枚举加三分,勉强卡了过去. 首先在AB上枚举一点,接着在CD上按时间三分. #include <cmath> #include <iostrea

【NOIP2016提高A组模拟8.14】疯狂的火神

题目 火神为了检验zone的力量,他决定单挑n个人. 由于火神训练时间有限,最多只有t分钟,所以他可以选择一部分人来单挑,由于有丽子的帮助,他得到了每个人特定的价值,每个人的价值由一个三元组(a,b,c)组成,表示如果火神在第x分钟单挑这个人(x指单挑完这个人的时间),他就会得到a-b*x的经验值,并且他需要c分钟来打倒这个人. 现在火神想知道,他最多可以得到多少经验值,由于火神本来就很笨,进入zone的疯狂的火神就更笨了,所以他希望你来帮他计算出他最多可以得到多少经验值. 分析 注意到这道题有

【NOIP2016提高A组模拟8.17】(雅礼联考day1)Binary

题目 分析 首先每个数对\(2^i\)取模.也就是把每个数的第i位以后删去. 把它们放进树状数组里面. 那么当查询操作, 答案就位于区间\([2^i-x,2^{i-1}-1-x]\)中,直接查询就可以了. 细节很多,注意处理. #include <cmath> #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algor

【NOIP2016提高A组模拟8.17】(雅礼联考day1)Value

题目 分析 易证,最优的答案一定是按\(w_i\)从小到大放. 我们考虑dp, 先将w从小到大排个序,再设\(f_{i,j}\)表示当前做到第i个物品,已选择了j个物品的最大值.转移就是\[f_{i,j}=max\left\{\begin{array}\\f_{i-1,j}\\f_{i-1,j-1}+v_i-w_i*(共选多少个物品(这个要枚举)-j)\end{array}\right.\] 但显然这是\(O(n^3)\)的. 我们考虑如何不用枚举共选多少个物品, 我们考虑反过来做,将w从大到小

【NOIP2016提高A组模拟8.15】Garden

题目 分析 其实原题就是[cqoi2012][bzoj2669]局部极小值. 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值. 给出所有局部极小值的位置,你的任务是判断有多少个可能的矩阵. 发现,X的位置最多有8个,那我们考虑状压dp. 我们从小到大把数填进去,用\(f_{i,j}\)表示,把第i个数填进去后,每个X是否被填了数,用二进制数j表示. 预处理出\(rest_j\)表示填充状态