IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Codeforces Round #610 (Div. 2) -> 正文阅读

[数据结构与算法]Codeforces Round #610 (Div. 2)

呜呜这场好难

A - Temporarily unavailable

题意

给定一个数轴,一个人从a点走到b点,c点有一个基站,覆盖半径是r,问这个人在走的过程中有多长时间没有信号

这个人的速度为1单位/分钟

题解

我们确定在 [ a , b ] [a,b] [a,b]区间内有多长的区间是有信号的,那么信号的起点就是 m a x ( a , c ? r ) max(a,c-r) max(a,c?r),这里假设 a ≤ b a\leq b ab

那么同理,信号的终点就是 m i n ( b , c + r ) min(b,c+r) min(b,c+r)

那么没有覆盖到的区间就是 b ? a ? ( m i n ( b , c + r ) ? m a x ( a , c ? r ) ) b-a-(min(b,c+r)-max(a,c-r)) b?a?(min(b,c+r)?max(a,c?r))

Code

int a, b, c, r;

void solve(){
    cin >> a >> b >> c >> r;
    if(a > b) swap(a, b);
    int st = max(a, c - r);
    int ed = min(b, c + r);

    cout << b - a - max(0, ed - st) << Endl;
}

B2 - K for the Price of One (Hard Version)

题意

有n个商品,p元钱

可以花 w i w_i wi?来买第 i i i个商品,也可以一次买 k k k个商品,而只需要花 m a x ( a i k ) max(a_{i_k}) max(aik??)

问最多能买多少个商品

题解1

这个题我们很容易的想到来用贪心来做,但是怎么贪确实学到了

我们首先明白第一个道理,单买一个高价值的不如单买一个低价值的

买k个的时候选比它小k-1个名次的肯定更好,这个很容易证明

那么我们知道,如果我们一次要买k个的话,一定是要买第k大的数开始买是最好的

其次如果买k个的话,肯定要是从小到大选择一个然后来以这个为起点选k个来买是最好的

那么如果我们单买的话也只会从前k-1个开始买了

题解2

看了看dp做法,但是对于菜鸡来说dp看题解简单,做起来难

首先上面的分析仍然适用

我们定义 d p [ i ] dp[i] dp[i]为以 i i i买以i号结尾的全部物品的最小价格

d p [ i ] = m i n ( d p [ i ? 1 ] + w [ i ] , d p [ i ? k ] + w [ i ] ) dp[i]=min(dp[i-1]+w[i],dp[i-k]+w[i]) dp[i]=min(dp[i?1]+w[i],dp[i?k]+w[i])

Code

1

int n, p, k;
int a[N];
int s[N];

void solve(){
    cin >> n >> p >> k;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
        s[i] = 0;
    }

    sort(a + 1, a + 1 + n);

    for(int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i];

    int ans = 0;
    
    for(int i = 0; i < k; i++){
        
        int summ = s[i];
        if(summ > p){
            break;
        }

        int cnt = i;

        for(int j = i + k; j <= n; j += k){
            if(summ + a[j] <= p){
                summ += a[j];
                cnt += k;
            }
            else break; 
        }

        ans = max(ans, cnt);
    }
    cout << ans << endl;
}

2

int n, p, k;
int a[N];
int f[N];

void solve(){
    cin >> n >> p >> k;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
    }

    sort(a + 1, a + 1 + n);

    for (int i = 1; i <= n; i++){
        f[i] = f[i - 1] + a[i];
        if(i >= k)
            f[i] = min(f[i], f[i - k] + a[i]);
    }

    int ans = 0;
    for (int i = 1; i <= n; i++){
        if(p >= f[i])
            ans = i;
    }
    cout << ans << endl;
}

C - Petya and Exam

题意

Petya将会参加一场考试,这场考试从时间点0开始,到T结束。考试中有n道题,分为两种,简单(需要花a时间做完)的题和困难(需要花b时间做完)的题(a <= b),即在时间点x开始做这道题,将会在x+a或x+b时间点完成。现在每道题会在时间点 ti 变成必须完成,Petya可以在0 ~ T任意一个时间点离开,若离开时有必须要完成的题目没有完成,他将会得到0分,否则会得到他完成的题目的分数。求他最大能得到的分数。

(来源洛谷)

题解

这个题的解法真的很妙,也又学到了

参考官方题解+https://www.bilibili.com/video/BV1FJ411s7E5?p=3

首先我们贪心的想,解决一个简单问题肯定是比解决一个难的问题是要优的

那么我们假设在t时间内交卷,那么我们必须完成的问题要花费ax+by,其中x为在t时间内必须完成的简单题的数量,同理,y为在t时间内必须完成的简单题的数量

那么我们解决了必须解决掉的时间,那么剩下的根据第一条原则,那么我们显然优先选简单的来做会更好,然后 有剩余的再选难的做

那么我们就只需要枚举每种时间,

那可不行,T的范围是1e9,是不能直接枚举的。

我们想一下,在枚举的过程中,显然有部分时间是没有必要算的,只有当时间到达 t i t_i ti?的时候才是必须要做的,那么在 t i ? 1 t_i-1 ti??1的时间是不需要一定做这个的

所以我们枚举 t i t_i ti?,这样只需要枚举n次即可

Code

#define int ll

int T;
int n, m, a, b;
int h[N];

void solve(){
    cin >> n >> m >> a >> b;

    int cnta = 0;
    int cntb = 0;
    vector<PII> q;

    for (int i = 0; i < n; i++){
        cin >> h[i];
    }
    for (int i = 0; i < n; i++){
        int t;
        cin >> t;
        q.pb({t, h[i]});
        if(h[i])
            cntb++;
        else
            cnta++;
    }

    sort(all(q));
    q.pb({m + 1, 0}); // m+1是因为我们最长时间是m时间,但是在公式里我们用的是t-1

    int ans = 0;
    int x = 0, y = 0;

    for (int i = 0; i <= n; i++){
        int need = x * a + y * b;
        int has = q[i].x - 1 - need;
        if(has >= 0){
            int A = min(cnta - x, has / a);
            has -= A * a;
            int B = min(cntb - y, has / b);
            ans = max(ans, x + y + A + B);
        }

        int j = i;
        while (j <= n && q[i].x == q[j].x){ // 看看有多少在下一时刻是必须要做的
            if(q[j].y)
                y++;
            else
                x++;
            j++;
        }
        i = j - 1;
    }

    cout << ans << endl;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:38:43  更:2022-04-01 23:40:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:44:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码