Codeforces Hello 2024 A~D,F1

A.Wallet Exchange(思维)

题意:

AliceBob各自拥有 a , b a,b a,b枚硬币,他们决定以Alice为先手开始比赛,比赛中每人在每轮需按顺序执行操作1和操作2:

  • 操作1:交换两人手上拥有的硬币数量,或什么都不做

  • 操作2:丢掉手上的一枚硬币(如果此时手上没有硬币则输掉比赛)

问:假设两人都极为聪明,那么谁会赢下这场比赛?

分析:

实际上对于操作1,比赛两方均会选择硬币较多的一堆,因此,可以将硬币视为只有一堆,共 n n n枚,其中 n = a + b n = a + b n=a+bAliceBob按顺序从这堆硬币中丢弃硬币。

此时若硬币数量 n n n为偶数时,必然是后手丢掉最后一枚硬币,即Bob获胜,反之,先手Alice获胜。

代码:

#include<bits/stdc++.h>

using namespace std;

void solve() {
    int a, b;
    cin >> a >> b;
    if ((a + b) % 2 == 0) {
        cout << "Bob" << endl;
    } else {
        cout << "Alice" << endl;
    }
}

int main() {
    int Case;
    cin >> Case;
    while (Case--) {
        solve();
    }
    return 0;
}

B.Plus-Minus Split(贪心)

题意:

给出一个包含 n n n个字符的字符串 s s s,字符串中仅包含字符-+,其中-代表 − 1 -1 1+代表 1 1 1

你可以进行以下步骤来计算罚分:

  1. 将字符串 s s s分为若干子子串 b 1 , b 2 , . . . , b k b_1, b_2, ..., b_k b1,b2,...,bk

  2. 对于字符串 c c c产生的罚分为 p ( c ) = ∣ c 1 + c 2 + . . . + c m ∣ ⋅ m p(c) = |c_1 + c_2 + ... + c_m| \cdot m p(c)=c1+c2+...+cmm

  3. 产生的总罚分为 p ( s ) = p ( b 1 ) + p ( b 2 ) + . . . + p ( b k ) p(s) = p(b_1) + p(b_2) + ... + p(b_k) p(s)=p(b1)+p(b2)+...+p(bk)

问:最小可能的罚分是多少?

分析:

为了最小化罚分,需要尽可能多的将正负号进行匹配,即若干子拆出的子串中正负号出现次数相同,但字符串中正负号数量并不一定相同,那么剩下的正号或负号依然会产生罚分,此时为了最小化罚分,必然选择这些正负号自身为一个子串,假设存在 a a a + + +号, b b b − - 号,那么最小罚分为 a + b − 2 × m i n ( a , b ) a + b - 2 \times min(a, b) a+b2×min(a,b)

代码:

#include<bits/stdc++.h>

using namespace std;

void solve() {
    int n;
    string s;
    cin >> n >> s;
    int add = 0, sub = 0;
    for (int i = 0; i < n; i++) {
        if (s[i] == '-') sub++;
        else add++;
    }
    cout << n - 2 * min(add, sub) << endl;
}

int main() {
    int Case;
    cin >> Case;
    while (Case--) {
        solve();
    }
    return 0;
}

C.Grouping Increases(贪心)

题意:

给出一个包含 n n n个数字的数组 a a a,你需要按以下要求计算罚分:

  1. 将数组 a a a分为两个子序列 s , t s, t s,t(可能有个子序列为空)。

  2. 对于一个包含 m m m个数字的数组 b b b,产生的罚分 p ( b ) = ∑ i = 1 m − 1 f ( i ) p(b) = \sum\limits_{i = 1}^{m - 1}f(i) p(b)=i=1m1f(i),其中 f ( i ) f(i) f(i)为满足 b i < b i + 1 b_i < b_{i + 1} bi<bi+1则为 1 1 1,不满足则为 0 0 0

  3. 总罚分为 p ( s ) + p ( t ) p(s) + p(t) p(s)+p(t)

问:最小可能的罚分是多少?

分析:

由于对于子序列的罚分计算只考虑相邻的两个数字,那么只需要维护两个子序列最后的元素。

b b b为两个子序列中最后元素中的较小值, c c c为较大值,并按以下要求检查 a i a_i ai该加入哪个子序列:

  • 如果 a i ≤ b a_i \le b aib,那么 a i a_i ai将会加入最后元素较小的序列,即 b = a i b = a_i b=ai

  • 否则,再检查是否满足 a i ≤ c a_i \le c aic,如果满足,则将 a i a_i ai加入最后元素较大的序列,即 c = a i c = a_i c=ai

  • 如果以上两种情况均不满足,那么此时必然产生一点罚分,并且为了使之后的罚分尽可能小,当前数字 a i a_i ai必然会加入尾部元素较小的序列,即 b = a i b = a_i b=ai

代码:

#include<bits/stdc++.h>

using namespace std;

int a[200005];

void solve() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];
    int b = 1e9, c = 1e9, ans = 0;
    for (int i = 0; i < n; i++) {
        if (b > c) {
            swap(b, c);
        }
        if (a[i] <= b) {
            b = a[i];
        } else if (a[i] <= c) {
            c = a[i];
        } else {
            b = a[i];
            ans++;
        }
    }
    cout << ans << endl;
}

int main() {
    int Case;
    cin >> Case;
    while (Case--) {
        solve();
    }
    return 0;
}

D.01 Tree(思维)

题意:

有一棵包含 n n n个叶节点的树,保证每个非叶节点均包含两个子节点,同时,对于所有非叶节点,走向子节点的边中均包含权值,且其中一条权值为 0 0 0,另一条权值为 1 1 1

你忘记了原本的树是什么样子的,只记得根节点到这 n n n个叶节点的权值之和,按dfs序给出这些叶节点的权值,问是否存在满足这些节点权值的树。

分析

由于每个非叶节点与子节点之间的边权分别为 0 , 1 0, 1 0,1,那么属于同一个父节点的两个节点的权值之差必然为 1 1 1,且权值较小的一个与父节点的权值一致,由此可知如果给出的叶节点合法,那么必然存在且仅存在一个叶节点的权值为 0 0 0

同时,由于叶节点以dfs序给出,那么属于同一个父节点的两个叶节点在dfs序中也必然相邻,为了便于处理,使用静态双向链表将 1 ∼ n 1 \sim n 1n这些节点按顺序连在一起。

由于非叶节点的权值与两个子节点的权值较小者相同,那么如果同时删除它的两个子节点(这两个子节点均为叶节点),该节点也会变成叶节点,为了便于处理,可以在操作时仅删除权值较大的节点,将另一个子节点视为删除后新产生的叶节点。

然后考虑从叶节点开始向上删除节点,按以下步骤执行:

  • 删除的节点,它在dfs序中相邻的两个节点中,必然存在一个节点的权值比它小 1 1 1(树上仅会存在一个权值为 0 0 0的节点,其他节点权值均大于 0 0 0),此时可以将节点视为待删除节点,放入大根堆中等待删除

  • 当从大根堆取出节点后,就需要对该节点进行删除操作了,由于该节点存储在静态双向链表上,那么需要同时修改前后节点的指针。

  • 然后检查当前节点删除后,左右两边相邻的节点能否进入待删除状态,如果能,就将节点也加入堆中。

删除完成后,如果仅剩下一个权值为 0 0 0的节点未被删除,那么就表示存在满足要求的树,否则,找不到满足要求的树。

代码:

#include<bits/stdc++.h>

using namespace std;

int n, a[200005], pre[200005], nxt[200005], vis[200005];
struct Node{
    int id, val;
    bool operator < (const Node &o) const {
        if (val != o.val) return val < o.val;
        return id > o.id;
    }
};

priority_queue<Node> Q;

int check(int x) {
    return x >= 1 && x <= n && (a[pre[x]] == a[x] - 1 || a[nxt[x]] == a[x] - 1);
}

void solve() {
    cin >> n;
    int zero = 0;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        pre[i] = i - 1;
        nxt[i] = i + 1;
        vis[i] = 0;
        if (a[i] == 0) zero++;
    }
    /*a[0]和a[n + 1]取-1时可能会导致a[1]=0或a[n]=0的情况入队,因此取不影响答案的-2*/
    a[0] = a[n + 1] = -2;
    if (zero == 0) {
        cout << "NO" << endl;
        return;
    }
    for (int i = 1; i <= n; i++) {
    /*找开始时就能进入待删除状态的节点*/
        if (check(i)) {
            vis[i] = 1;
            Q.push(Node{i, a[i]});
        }
    }
    while (!Q.empty()) {
        Node u = Q.top();
        Q.pop();
        /*相当于双向链表中删点,需将前后连起来*/
        nxt[pre[u.id]] = nxt[u.id];
        pre[nxt[u.id]] = pre[u.id];
        /*检查左右的节点能否进入待删除状态*/
        if (vis[nxt[u.id]] == 0 && check(nxt[u.id])) {
            vis[nxt[u.id]] = 1;
            Q.push(Node{nxt[u.id], a[nxt[u.id]]});
        }
        if (vis[pre[u.id]] == 0 && check(pre[u.id])) {
            vis[pre[u.id]] = 1;
            Q.push(Node{pre[u.id], a[pre[u.id]]});
        }
    }
    /*由于权值为0的节点必然不会被删除,那么只需要判断剩余的节点数量.
    如果为1,那么剩下的节点权值必然为0*/
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        if (vis[i] == 0) {
            cnt++;
        }
    }
    if (cnt == 1) cout << "YES" << endl;
    else cout << "NO" << endl;
}

int main() {
    int Case;
    cin >> Case;
    while (Case--) {
        solve();
    }
    return 0;
}

E. 更新中…

F1.Wine Factory (Easy Version)(后缀和,线段树)

题意:

n n n座水塔,其中第 i i i座包含 a i a_i ai升的水,且拥有一个能消除 b i b_i bi升水的法师,同时相邻两座水塔之间拥有一道阀门,第 i i i座高塔与第 i + 1 i + 1 i+1座水塔之间的阀门允许通过 c i c_i ci升水。

对于第 i ( i = 1 , 2 , . . . , n ) i(i = 1, 2, ..., n) i(i=1,2,...,n)座塔,将会进行以下操作:

  1. 法师将水塔 i i i中最多 b i b_i bi升的水消除,并将消除的水转化为等量的红酒。

  2. 如果 i ≠ n i \ne n i=n,那么至多 c i c_i ci升水可以由阀门流到第 i + 1 i + 1 i+1座水塔。

题目将给出 q q q次更新,每次给出四个数字 p , x , y , z p, x, y, z p,x,y,z,即将 a p = x , b p = y , c p = z a_p = x, b_p = y, c_p = z ap=x,bp=y,cp=z,并要求对于每次更新,输出最多能获得多少升红酒。

特殊条件:对于所有数据,有 c i = 1 0 18 , z = 1 0 18 c_i = 10^{18}, z = 10^{18} ci=1018,z=1018

分析:

对于特殊条件, c i , z c_i, z ci,z均为 1 0 18 10^{18} 1018,由于 ∑ i = 1 n m a x ( a i ) = 5 × 1 0 14 < 1 0 18 \sum\limits_{i = 1}^{n}max(a_i) = 5 \times 10^{14} < 10^{18} i=1nmax(ai)=5×1014<1018,那么如果水塔中的水没有被全部消除,则剩下的水均能流到下一座高塔,即可以不考虑 c i c_i ci这个限制因素。

先考虑每座水塔自身无法消除的水量: v i = a i − b i v_i = a_i - b_i vi=aibi,当 v i > 0 v_i > 0 vi>0时,未被消除的水量必然需要由后面的法师来进行消除(如果可以的话),因此对于水塔 k k k而言,无法消除的水量实际为 f ( k ) = ∑ i = k n v i f(k) = \sum\limits_{i = k}^{n}v_i f(k)=i=knvi。那么对于所有水塔来说,无法消除的水量即为 m a x ( f ( 1 ) , f ( 2 ) , . . . , f ( n ) ) max(f(1), f(2), ..., f(n)) max(f(1),f(2),...,f(n))

使用后缀和建一棵线段树,维护区间上的最大值,并使用变量 s u m sum sum记录水塔的总水量。

每次更新水塔 p p p时,由于线段树维护的是后缀和,那么对于所有 ( p + 1 ) ∼ n (p + 1) \sim n (p+1)n上的点,均不会收到影响,只需要对区间 1 ∼ p 1 \sim p 1p进行更新,先减去原本的 v p v_p vp,再加上当前更新后的新 v p = x − y v_p = x - y vp=xy

那么最后的答案就是 s u m − m a x ( f ( 1 ) , f ( 2 ) , . . . , f ( n ) ) sum - max(f(1), f(2), ..., f(n)) summax(f(1),f(2),...,f(n)),其中 m a x ( f ( 1 ) , f ( 2 ) , . . . , f ( n ) ) max(f(1), f(2), ..., f(n)) max(f(1),f(2),...,f(n))为线段树树根中记录的信息。

代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 5e5 + 5e2;

LL n, q, a[N], b[N];
LL sum, T[N << 2], lazy[N << 2], c[N], v[N], sv[N];

void pushup(int x) {
    T[x] = max(T[x << 1], T[x << 1 | 1]);
}

void build(int l, int r, int x) {
    if (l == r) {
        T[x] = sv[l];
        return;
    }
    int mid = l + r >> 1;
    build(l, mid, x << 1);
    build(mid + 1, r, x << 1 | 1);
    pushup(x);
}

void pushdown(int x) {
    if (lazy[x]) {
        lazy[x << 1] += lazy[x];
        lazy[x << 1 | 1] += lazy[x];
        T[x << 1] += lazy[x];
        T[x << 1 | 1] += lazy[x];
        lazy[x] = 0;
    }
}

void update(int l, int r, int x, int ul, int ur, LL val) {
    if (l >= ul && r <= ur) {
        T[x] += val;
        lazy[x] += val;
        return;
    }
    pushdown(x);
    int mid = l + r >> 1;
    if (ul <= mid) update(l, mid, x << 1, ul, ur, val);
    if (ur > mid) update(mid + 1, r, x << 1 | 1, ul, ur, val);
    pushup(x);
}

void solve() {
    cin >> n >> q;
    sum = 0;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) cin >> b[i];
    for (int i = 1; i < n; i++)  cin >> c[i];
    for (int i = n; i >= 1; i--) {
        v[i] = a[i] - b[i];
        sv[i] = v[i] + sv[i + 1];
        sum += a[i];
    }
    build(1, n, 1);
    while (q--) {
        int p, x, y;
        LL z;
        cin >> p >> x >> y >> z;
        sum -= a[p];//减去原本的水量
        /*减掉原本的vp*/
        update(1, n, 1, 1, p, -v[p]);
        a[p] = x;
        b[p] = y;
        v[p] = x - y;//更新vp
        sum += a[p];//加上现在的水量
        /*加上现在的vp*/
        update(1, n, 1, 1, p, v[p]);
        /*出现负数说明所有水均能消除,此时需要减去的值为0,需取max*/
        cout << sum - max(0ll, T[1]) << endl;
    }
}

int main() {
    ios::sync_with_stdio(false);
    int Case = 1;
    while (Case--) {
        solve();
    }
    return 0;
}

学习交流

以下为学习交流QQ群,群号: 546235402,每周题解完成后都会转发到群中,大家可以加群一起交流做题思路,分享做题技巧,欢迎大家的加入。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/305116.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java学习笔记-day02-在IDEA中使用git忽略提交.idea下的文件

1.在根目录.gitignore文件排除.idea目录 ### IntelliJ IDEA ### .idea2.使用重置Head还原已经add过的文件 创建项目时&#xff0c;可能会有.idea中的文件先add到git后再创建的.gitignore文件&#xff0c;导致文件commit时无法排除&#xff0c;如下所示。 使用重置Head将文件…

工业数据采集分析——工厂大脑 提升综合经济效益

随着企业对数字化的认知越来越清晰&#xff0c;对工业数智化的战略越来越明确&#xff0c;企业的诉求也在发生转变。中国的工业企业经过近几十年的发展&#xff0c;自动化、信息化&#xff0c;以及一些基础的数据系统建设在不同的行业中慢慢地推进。近几年&#xff0c;工业企业…

桶装水在线订水送水系统平台搭建

在线订水系统&#xff0c;为您带来更快捷、更优质的服务。不仅是用户福音&#xff0c;更是商家营销利器。一体化管理&#xff0c;轻松搞定用户、水站、商品、订单及售后。多种营销活动&#xff0c;激发用户复购意愿。 功能亮点如下&#xff1a; 1. 注册登录&#xff1a;手机号…

vscode使用npm安装element-UI并添加router路由

npm安装vue&#xff0c;添加淘宝镜像-CSDN博客 elementUI安装与配置 安装可以看我上一篇文章 vscode控制台输入指令 npm i element-ui -S 安装完成后在目录结构打开下图文件 可以看到多了一行elementui就代表安装成功了 下面是项目常用的结构 安装完成后需要启用elementU…

[C#]winform部署yolov5-onnx模型

【官方框架地址】 https://github.com/ultralytics/yolov5 【算法介绍】 Yolov5&#xff0c;全称为You Only Look Once version 5&#xff0c;是计算机视觉领域目标检测算法的一个里程碑式模型。该模型由ultralytics团队开发&#xff0c;并因其简洁高效的特点而备受关注。Yol…

C#编程-实现重写

实现重写 实现派生类中基类的成员称为重写。在C#中,可以重写方法、属性和索引器。 重写是多态性的一种形式,因为它使您能够创建具有相同名称和不同功能的不同代码块。 重写函数 在面向对象编程中,子类可以提供超类中已定义的专门版本的函数。这称为函数重写。 函数重写是…

模型创建与nn.Module

一、网络模型创建步骤 二、nn.Module 下面描述了在 PyTorch 中常见的一些属性和功能&#xff0c;用于存储和管理神经网络模型的参数、模块、缓冲属性和钩子函数。 parameters&#xff1a;用于存储和管理 nn.Parameter 类的属性。nn.Parameter 是一种特殊的张量&#xff0c;它被…

Python教程38:使用turtle画动态粒子爱心+文字爱心

Turtle库是Python语言中的一个标准库&#xff0c;它提供了一种有趣的方式来介绍编程和图形绘制的基本概念。Turtle库使用一个虚拟的“海龟”来绘制图形。你可以控制海龟的方向、速度和位置&#xff0c;通过向前移动、向左转或向右转等命令来绘制线条、圆弧多边形等图形。 -----…

《Shader开发实战》-笔记

一、初识游戏图形 1、什么是渲染&#xff1f; 渲染实际上就是创建图像的过程&#xff0c;在渲染过程中创建的图像被称为渲染或者帧&#xff0c;该图像&#xff08;帧&#xff09;以每秒多次在计算机屏幕上进行呈现&#xff0c;即帧率。 负责渲染图像&#xff08;帧&#xff09…

深度解析分布式锁及实现方案

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

赠送葡萄酒:为别人选择合适的葡萄酒

葡萄酒可以在许多不同的场合成为很好的礼物&#xff0c;因为它可以用来庆祝许多不同的事情。当被邀请去别人家时&#xff0c;你可以带酒去吃饭。葡萄酒可以用来纪念婚礼、出生、毕业和各种纪念日&#xff0c;来自云仓酒庄品牌雷盛红酒分享这是一个非常合适的专业礼物。但是你怎…

LeetCode 2125. 银行中的激光束数量【数组,遍历】1280

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

基于共享储能电站的工业用户日前优化经济调度【复现】

文章提出一种基于共享储能电站的工业用户日前优化经济调度方法。首先提出共享储能电站的概念&#xff0c;分析其 商业运营模式。然后将共享储能电站应用到工业用户经济优化调度中&#xff0c;通过协调各用户使用共享储能电站进行充电和 放电的功率&#xff0c;实现用户群日运行…

数据湖存储解决方案之Iceberg

1.Iceberg是什么&#xff1f; Apache Iceberg 是由 Netflix 开发开源的&#xff0c;其于2018年11月16日进入 Apache 孵化器&#xff0c;是 Netflix 公司数据仓库基础。Apache Iceberg设计初衷是为了解决Hive离线数仓计算慢的问题&#xff0c;经过多年迭代已经发展成为构建数据…

【NextChat】手把手教您如何在群晖上部署chatgpt-next-web

文章目录 📖 介绍 📖🏡 环境 🏡📒 配置方法 📒📝 群晖部署📝 Vercel/Dokcer/其他环境部署⚓️ 相关链接 ⚓️📖 介绍 📖 chatgpt-next-web项目又叫NextChat,是一个支持一键免费部署你的私人GPT 的网页应用,支持 GPT3、 GPT4 & Gemini Pro 等模型,本…

STM32——高级定时器输出指定个数PWM波原理及实战

1.高级定时器简介&#xff08;TIM8、TIM1&#xff09; 相比于通用定时器特性&#xff1a; 1&#xff09;重复计数器 2&#xff09;死区时间带可编程的互补输出 3&#xff09;断路输入&#xff0c;用于将定时器的输出信号置于用户可选的安全配置中 2.高级定时器框图 3.重复计数…

SSM(spring+springmvc+mybatis)整合

spring与SpringMvc的常用注解 一、spring常用注解&#xff1a; Component&#xff1a;实现bean的注入&#xff08;不过获取bean需要用bean的类型来获取&#xff08;即class文件&#xff09;&#xff09; controller、Service、Repository的作用等同于Component注解的作用&…

TS中的类

目录 ES6的类 类的概念 类的构成 类的创建 声明 构造函数 定义内容 创建实例 TS中的类 类声明 构造函数 属性和方法 实例化类 继承 访问修饰符 public private protected 成员访问修饰符的使用原则 访问器 只读成员与静态成员 readonly static 修饰符总…

remote-ssh如何离线下载历史版本

remote-ssh离线下载任意历史版本方法&#xff0c;简单有效 很多小伙伴都会遇到这样的问题&#xff0c;由于内网服务器中安装的vs code版本较低&#xff0c;比如1.62.0版本&#xff0c;官网发布的version history 只展示最新的五个版本&#xff0c;还是太高了&#xff0c;导致下…

TypeScript 和 jsdom 库创建爬虫程序示例

TypeScript 简介 TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集&#xff0c;可以编译生成纯 JavaScript 代码。TypeScript 增加了可选的静态类型和针对对象的编程功能&#xff0c;使得开发更加大规模的应用容易。 jsdom 简介 jsdom 是一个…