CodeForce---Educational Codeforces Round 3 D. Gadgets for dollars and pounds 正题

对于这题笔者无解,只有手抄一份正解过来了:

基本思想就是 :

  • 二分答案,对于第x天,计算它最少的花费f(x),<=s就是可行的,这是一个单调的函数,所以可以二分。
  • 对于f(x)的计算,我用了nlog(n)的算法,遍历m个商品,用c[i]乘以前x天里,第t[i]种货币的最便宜的价格,存放到一个数组里,之后排序,计算前k个的和就是f(x)
  • 前x天里,第t[i]种货币的最便宜的价格是通过预处理得到的,很容易的计算一下前缀最小值就行了。

贴代码吧:

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pii;
#define fi first
#define se second
#define mp make_pair
const int maxn = 200005;
int a[maxn],b[maxn],t[maxn],c[maxn];
int n,m,k,s;
int am[maxn],bm[maxn];
int ida[maxn],idb[maxn];
const int inf = 0x3f3f3f3f;

pii pli[maxn];
int id[maxn];

ll f(int x){
    ll ret = 0;
    for (int i=1;i<=m;i++){
        if (t[i] == 1){
            pli[i].fi = (ll)c[i] * (ll)am[x];

        }
        else{
            pli[i].fi = (ll)c[i] * (ll)bm[x];
        }
        pli[i].se = i;
    }
    sort(pli+1,pli+m+1);
    for (int i=1;i<=k;i++){
        ret += pli[i].fi;
    } 

    return ret;
}

int main(){
    cin>>n>>m>>k>>s;
    am[0] = bm[0] = inf;
    for (int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if (a[i] < am[i-1]){
            am[i] = a[i];
            ida[i] = i;
        }
        else{
            am[i] = am[i-1];
            ida[i] = ida[i-1];
        }
    }
    for (int i=1;i<=n;i++){
        scanf("%d",&b[i]);
        if (b[i] < bm[i-1]){
            bm[i] = b[i];
            idb[i] = i;
        }
        else{
            bm[i] = bm[i-1];
            idb[i] = idb[i-1];
        }
    }
    for (int i=1;i<=m;i++){
        scanf("%d%d",&t[i],&c[i]);
    }

    ll low,high,mid;
    low = 1,high = n;
    ll d = -1;
    while(low <= high){
        mid = (low + high) / (ll)2;
        if (f(mid) <= s){
            high = mid - 1;
            d = mid;
            for (int i=1;i<=k;i++){
                id[i] = pli[i].se;
            }
        }
        else{
            low = mid + 1;
        }
    }
    cout << d <<"\n";
    if (d == (ll)-1)
        return 0;
    int x = (int)d;
    for (int i=1;i<=k;i++){
        printf("%d %d\n",id[i],t[id[i]]==1?ida[x]:idb[x]);
    }

    return 0;
}
时间: 2024-08-05 04:39:55

CodeForce---Educational Codeforces Round 3 D. Gadgets for dollars and pounds 正题的相关文章

Educational Codeforces Round 3:D. Gadgets for dollars and pounds(二分答案+贪心)

看了菊苣的理解才知道怎么写..根本没思路啊一开始... 天数肯定在1~n之间,二分答案. 可以用保存前i天的最低美元和英镑汇率,没有规定哪天买,每天也没有购买数量限制,所以二分出一个答案mid的后,就在前mid天中汇率最低的时候一次性购入最便宜的就行了,judge一下总花费 打印答案的时候以ans为结果,再模拟一遍就好 #include"cstdio" #include"queue" #include"cmath" #include"s

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

题目链接:Educational Codeforces Round 21 G. Anthem of Berland 题意: 给你两个字符串,第一个字符串包含问号,问号可以变成任意字符串. 问你第一个字符串最多包含多少个第二个字符串. 题解: 考虑dp[i][j],表示当前考虑到第一个串的第i位,已经匹配到第二个字符串的第j位. 这样的话复杂度为26*n*m*O(fail). fail可以用kmp进行预处理,将26个字母全部处理出来,这样复杂度就变成了26*n*m. 状态转移看代码(就是一个kmp

Educational Codeforces Round 26 D. Round Subset(dp)

题目链接:Educational Codeforces Round 26 D. Round Subset 题意: 给你n个数,让你选其中的k个数,使得这k个数的乘积的末尾的0的个数最大. 题解: 显然,末尾乘积0的个数和因子2和因子5的个数有关. 然后考虑dp[i][j]表示选i个数,当前因子5的个数为j时,能得到因子2最多的为多少. 那么对于每个数,记录一下因子2和5的个数,做一些01背包就行了. 1 #include<bits/stdc++.h> 2 #define mst(a,b) me

CodeForces 837F - Prefix Sums | Educational Codeforces Round 26

按tutorial打的我血崩,死活挂第四组- - 思路来自FXXL /* CodeForces 837F - Prefix Sums [ 二分,组合数 ] | Educational Codeforces Round 26 题意: 设定数组 y = f(x) 使得 y[i] = sum(x[j]) (0 <= j < i) 求初始数组 A0 经过多少次 f(x) 后 会有一个元素 大于 k 分析: 考虑 A0 = {1, 0, 0, 0} A1 = {1, 1, 1, 1} -> {C(

Educational Codeforces Round 26 D dp,思维

Educational Codeforces Round 26 D. Round Subset 题意:有 n 个数,从中选出 k 个数,要使这 k 个数的乘积末尾的 0 的数量最多. tags:dp好题 dp[i][j][l] 表示前 i 个数,选取了其中 j 个数,分解因子后有 l 个 5时,最多有多少个 2 .i 这一维明显可以省略. 这题一开始有个地方写挫了..选取 j 个数时,应该反着来,即 for( j, k, 1) ,不是 for( j, 1, k) ,不然会多算. #include

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

Educational Codeforces Round 23 D. Imbalanced Array(单调栈)

题目链接:Educational Codeforces Round 23 D. Imbalanced Array 题意: 给你n个数,定义一个区间的不平衡因子为该区间最大值-最小值. 然后问你这n个数所有的区间的不平衡因子和 题解: 对每一个数算贡献,a[i]的贡献为 当a[i]为最大值时的 a[i]*(i-l+1)*(r-i+1) - 当a[i]为最小值时的a[i]*(i-l+1)*(r-i+1). 计算a[i]的l和r时,用单调栈维护.具体看代码,模拟一下就知道了. 然后把所有的贡献加起来.

Educational Codeforces Round 25 F. String Compression(kmp+dp)

题目链接:Educational Codeforces Round 25 F. String Compression 题意: 给你一个字符串,让你压缩,问压缩后最小的长度是多少. 压缩的形式为x(...)x(...)  x表示(...)这个出现的次数. 题解: 考虑dp[i]表示前i个字符压缩后的最小长度. 转移方程解释看代码,这里要用到kmp来找最小的循环节. 当然还有一种找循环节的方式就是预处理lcp,然后通过枚举循环节的方式. 这里我用的kmp找的循环节.复杂度严格n2. 1 #inclu

Educational Codeforces Round 23 E. Choosing The Commander (trie)

题目链接: Educational Codeforces Round 23 E. Choosing The Commander 题意: 一共有n个操作. 1.  插入一个数p 2.  删除一个数p 3.  询问有多少个数 使得 x^p<l 题解: 对于前两种操作用01trie就能解决. 对于对三个操作,我们考虑在trie上搜索. 1.  当l的bit位是1时,那边bit位是p的字数全部的数都会小于l,(因为p^p=0) 2.  当l的bit为是0时,那边只能向bit位是p的子树中搜. 这样算下来