寒假思维训练day20

更新一道1600的反向贪心


题意:

有n场比赛,且小明的智商是m,每场比赛需要的智商是a[i],当m >= a[i]时, 可以直接看题,当a[i] > m时,需要智商m减1才能看这道题,当智商为0不能继续往下看题,问最多能看多少题


题解:

1、已知n, m, a[1],..., a[n]

2、

m >= n时,我们直接可以全部都看,答案为n。

m < n时,假设最优解为:\{a[i_1], a[i_2], a[i_3], ..., a[i_k]\}, 我们来构造出一个等价的解,我们此时来看最后一次选择, 当看i_k != n时,必然要有m >= 1, 那么此时因为最优解当中不存在n, 显然m恰好为1, 那我们不妨不选i_k,选择n,此时我们的解可以构造成\{a[i_1], a[i_2], a[i_3], ..., a[n]\}, 在此基础上我们进行贪心,往前贪心,因为到a[n]时我们的智商 >= 1,那我们从后往前倒推,定初始值sum = 0, 当sum >= a[i], 我们取走i, 只要sum < m, 我们取走当前位,sum += 1,因为当尽可能多的取走可以使得sum 尽可能更早地逼近m, 对前面的选择更有利 。


代码 (cpp):

#include <bits/stdc++.h>
#define int long long 
#define lowbit(x) (x&-x)
using namespace std; 
const int N = 2e5 + 10; 
const int inf = 0x3f3f3f3f; 
int n, m;  
int a[N]; 
int cn[N]; 
void solve() {
    cin >> n >> m; 
    for(int i = 1; i <= n; i ++ ) cin >> a[i]; 
    vector<int> ans(n + 1, 0); 
    int t = 0; 
    for(int i = n; i >= 1; i -- ) {
        if(t >= a[i]) ans[i] = 1; 
        else if(t < m) t ++, ans[i] = 1; 
    }
    for(int i = 1; i <= n; i ++ ) cout << ans[i]; 
    cout << endl; 
    
}
signed main() {
    int ts; 
    cin >> ts; 
    while(ts -- ) solve(); 
    
    return 0; 
}
/* 

1
5 4
5 1 5 1 4 3 

*/ 

相关推荐

  1. 2024.1.28 寒假训练记录(11)

    2024-02-12 14:08:01       43 阅读
  2. 2024.2.15 寒假训练记录(24

    2024-02-12 14:08:01       29 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-12 14:08:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-12 14:08:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-12 14:08:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-12 14:08:01       20 阅读

热门阅读

  1. <网络安全>《28 工业安全态势感知平台》

    2024-02-12 14:08:01       28 阅读
  2. visual studio2019中调用C文件中函数报错的问题分析

    2024-02-12 14:08:01       27 阅读
  3. 倒计时57天

    2024-02-12 14:08:01       37 阅读
  4. 「优选算法」:山脉数组的峰顶索引

    2024-02-12 14:08:01       25 阅读
  5. C语言的数组

    2024-02-12 14:08:01       29 阅读
  6. C# Thread的使用

    2024-02-12 14:08:01       34 阅读
  7. 时间函数举例2

    2024-02-12 14:08:01       32 阅读
  8. 求小数的某一位(c++题解)

    2024-02-12 14:08:01       31 阅读