Educational Codeforces Round 161 (Div.2) A~F

A.Tricky Template (模拟)

题意:

询问是否存在一个字符串模板 t t t使得字符串 a a a b b b与之匹配, c c c不匹配,匹配条件如下:

  • 如果模板中第 i i i个字母是小写字母,那么 s i s_i si必须与 t i t_i ti相同。
  • 如果模板中的第 i i i个字母是大写字母,那么 s i s_i si必须与 t i t_i ti的小写字母不同。例如,如果模板中有字母 A A A,则在字符串的相应位置不能使用字母 a a a

分析:

如果字符串 c c c中有一个字符和字符串 a a a,字符串 b b b都不同就存在符合条件的字符串模板 t t t

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        string a, b, c;
        cin >> n >> a >> b >> c;
        bool flag = 0;
        for (int i = 0; i < n; i++)
            if (c[i] != a[i] && c[i] != b[i]) {
                flag = 1;
                break;
            }

        if (flag)
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
    return 0;
}

B.Forming Triangles (模拟)

题意:

n n n根木棍,第 i i i根木棍长度为 2 a i 2^{a_i} 2ai。询问从 n n n根木棍中选出 3 3 3根木棍组成一个三角形的方案数。

分析:

先使用计数排序(桶的思想)统计各个数字的出现次数,然后考虑合法的情况。

合法的情况有两种:

  • 同种长度木棍选择两根,再选一根短的木棍。
  • 选择长度相等的三根木棍。

简单组合数公式计算即可。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        vector<LL> a(n + 1);
        for (int i = 0; i < n; i++) {
            int x;
            cin >> x;
            a[x]++;
        }
        LL ans = 0;
        LL lst = 0;
        for (int i = 0; i <= n; i++) {
            LL x = a[i];
            if (x >= 2) {
                ans += x * (x - 1) / 2 * lst;
            }
            if (x >= 3) {
                ans += x * (x - 1) * (x - 2) / 6;
            }
            lst += x;
        }
        cout << ans << endl;
    }
    return 0;
}

C. Closest Cities (前缀和)

题意:

n n n个城市分布在一个数轴上,第 i i i个城市的坐标为 a i a_i ai,保证 a i a_i ai升序,并保证对于每一个 i i i,距离他最近的城市只有一个。有两种城市间移动的方式:

  • 花费 1 1 1元转移到当前所在城市最近的城市。

  • 花费 ∣ a x − a y ∣ \vert a_x-a_y \vert axay元,从 x x x移动到 y y y

给出 m m m次询问,每次给出两个城市 x x x, y y y,询问从 x x x y y y最少需要花费多少元。

分析:

可以发现,最优的移动方式一定是尽量选择转移到离当前城市最近的城市。可以分别计算从前到后和从后到前两个方向的花费,分别维护从前到后和从后到前的前缀和即可。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const LL inf = 1e18;

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        vector<LL> a(n + 2);
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        a[0] = -inf;
        a[n + 1] = inf;
        vector<LL> sum1(n + 2), sum2(n + 2);
        for (int i = 1; i <= n; i++) {
            if (a[i + 1] - a[i] < a[i] - a[i - 1])
                sum1[i + 1] = sum1[i] + 1;
            else
                sum1[i + 1] = sum1[i] + a[i + 1] - a[i];
        }
        for (int i = n; i >= 1; i--) {
            if (a[i] - a[i - 1] < a[i + 1] - a[i])
                sum2[i - 1] = sum2[i] + 1;
            else
                sum2[i - 1] = sum2[i] + a[i] - a[i - 1];
        }
        int m;
        cin >> m;
        for (int i = 1; i <= m; i++) {
            int x, y;
            cin >> x >> y;
            LL ans = 0;
            if (y > x)
                ans = sum1[y] - sum1[x];
            else
                ans = sum2[y] - sum2[x];
            cout << ans << endl;
        }
    }
    return 0;
}

D.Berserk Monsters(模拟)

题意:

Monocarp在打怪。

一排有 n n n个怪物,编号从 1 1 1 n n n。其中第 i i i个怪物有两个参数:攻击值等于 a i a_i ai,防御值等于 d i d_i di。为了杀死这些怪物,Monocarp给它们施放了狂暴咒语,因此它们会互相攻击,而不是攻击Monocarp。

战斗由 n n n个回合组成。每回合都会发生以下情况:

  • 首先,每个活着的怪物 i i i都会对左边最近的活着的怪物(如果存在)和右边最近的活着的怪物(如果存在)造成 a i a_i ai伤害;
  • 然后,每只在本回合中受到超过 d j d_j dj伤害的活着的怪物 j j j都会死亡。也就是说,当且仅当第 j j j个怪物的防御值 d j d_j dj小于它在本轮受到的总伤害时,它才会死亡。

计算每一轮中死亡的怪物数量。

分析:

这道题的本质是模拟,我们可以想到对于每个结点,我们都需要找他的左右两个相邻的结点,因此我们采取链表的写法,用链表维护相邻的怪物,随后在每一次遍历的过程中找到死亡的结点,随后对左右节点的前驱和后继进行改变。每一轮遍历都会将死亡的结点进行消除,即改变了死亡结点的前驱和后继,因此我们每次对上一轮被消灭的怪物相邻的怪物进行处理即可。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const LL mod = 998244353;
const LL N = 5e5;
int n, a[N], d[N], killed[N];
int l[N], r[N];

void Solve() {
    queue<int> q1, q2, q3;
    int len = 0;
    for (int i = 1; i <= n; i++)
        q1.push(i);
    for (int i = 1; i <= n; i++) {
        int ans = 0;
        while (!q1.empty()) {
            int x = q1.front();
            q1.pop();
            if (killed[x] || x <= 0 || x > n)
                continue;
            if (d[x] < a[l[x]] + a[r[x]]) {
                if (!killed[x]) ++ans, killed[x] = 1;
                q2.push(x);
            }
        }
        cout << ans << " ";
        len++;
        if (ans == 0)
            break;

        while (!q2.empty()) {
            int x = q2.front();
            q2.pop();
            q3.push(x);
            r[l[x]] = r[x];
            l[r[x]] = l[x];
        }
        while (!q3.empty()) {
            int x = q3.front();
            q3.pop();
            q1.push(l[x]), q1.push(r[x]);
        }
    }
    for (int i = len + 1; i <= n; i++)
        cout << "0 ";
    cout << endl;
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        cin >> n;
        a[0] = a[n + 1] = 0;
        d[0] = d[n + 1] = 0;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        for (int i = 1; i <= n; i++) {
            killed[i] = 0;
            l[i] = i - 1, r[i] = i + 1;
        }
        for (int i = 1; i <= n; i++)
            cin >> d[i];
        Solve();
    }
    return 0;
}

E.Increasing Subsequences(构造)

题意:

数组 a a a的递增子序列是指在不改变其余元素顺序的情况下,通过移除某些元素而得到的序列,并且其余元素是严格递增的(即 a b 1 < a b 2 < ⋯ < a b k a_{b_1} \lt a_{b_2} \lt \dots \lt a_{b_k} ab1<ab2<<abk b 1 < b 2 < ⋯ < b k b_1 \lt b_2 \lt \dots \lt b_k b1<b2<<bk)。注意,空子序列也是递增的。

给你一个正整数 X X X。找出一个长度最多 200 200 200的整数数组,使得它恰好有 X X X个递增的子序列,若没有这样的数组,输出 − 1 -1 1。如果有多个答案,输出其中任何一个。

如果两个子序列由相同的元素组成,但对应数组中的不同位置,则认为它们是不同的(例如,数组 [ 2 , 2 ] [2,2] [2,2]有两个不同的子序列等于 [ 2 ] [2] [2])。

分析:

考虑从大往小地向序列中加数。为了最小化所需数量至少要有一个长度为 ⌊ log ⁡ 2 X ⌋ ⌊\log2X⌋ log2X的递增数列,考虑能否复用这个递增数列中的某些元素来凑出其他 2 2 2的幂出来。

假设当前序列的答案为 k k k,若在当前已有数组的右边加一个最大值,或者加一个比之前所有数都小的数在最左边,那么新生成的序列的答案就为 2 k 2k 2k,加一个比之前所有数都小的数在右边的话新生成的序列的答案就为 k + 1 k+1 k+1

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const LL mod = 998244353;
const LL N = 5e5;
LL t, X;

int main() {
    cin >> t;
    while (t--) {
        cin >> X;
        LL high;
        for (LL i = 61; i >= 0; --i) {
            if ((X >> i) & 1LL) {
                high = i;
                break;
            }
        }
        deque<int> ans;
        ans.push_back(0);
        LL lst = 0;
        for (LL i = high - 1; i >= 1; --i) {
            if ((X >> i) & 1LL) {
                ans.push_back(--lst);
                ans.push_front(--lst);
            } else
                ans.push_front(--lst);
        }
        if (X & 1LL)
            ans.push_back(--lst);;
        cout << ans.size() << endl;
        for (auto x: ans) {
            cout << x << " ";
        }
        cout << endl;
    }
    return 0;
}

F.Replace on Segment(区间DP)

题意:

给你一个数组 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,,an,其中每个元素都是从 1 1 1 x x x的整数。

你可以多次对它进行下面的操作:

  • 选择三个整数 l l l r r r k k k,使得 1 ≤ l ≤ r ≤ n 1 \le l \le r \le n 1lrn 1 ≤ k ≤ x 1 \le k \le x 1kx和一个元素 a i a_i ai,使得 l ≤ i ≤ r l \le i \le r lir k k k不同。然后,对于每个 i ∈ [ l , r ] i \in [l, r] i[l,r],用 k k k替换 a i a_i ai

换句话说,在数组中选择一个子段,并从 1 1 1 x x x中选择一个未在该子段中出现的整数,然后用该整数替换子段中的每个元素。

为使数组中的所有元素相等。最少需要进行多少次操作?

分析:

f l , r , j f_{l,r,j} fl,r,j为使区间 [ l , r ] [l,r] [l,r]元素都为 j j j的最小操作数,设数组 g l , r , j g_{l,r,j} gl,r,j表示在区间 [ l , r ] [l,r] [l,r]中没出现过元素 j j j的方案数。

考虑 f f f数组转移。第一种是直接从 g g g转移到 f f f,即对没出现过 j j j的区间 [ l , r ] [l,r] [l,r]直接耗费 1 1 1全部变成 j j j。即: f l , r , j = g l , r , j + 1 f_{l,r,j}=g_{l,r,j}+1 fl,r,j=gl,r,j+1。第二种是区间合并,需要枚举中转点 m i d mid mid,此时 f l , r , j = f l , m i d , j + f m i d + 1 , r , j f_{l,r,j}=f_{l,mid,j}+f_{mid+1,r,j} fl,r,j=fl,mid,j+fmid+1,r,j

考虑 g g g数组转移。第一种是从 g g g转移, g g g数组需要变成没有出现过数 z z z的最小方案数,即 g l , r , k = g l , r , j + 1 g_{l,r,k}=g_{l,r,j}+1 gl,r,k=gl,r,j+1
第二种仍为区间合并,枚举中转点即可,即 g l , r , j = g l , m i d , j + g m i d + 1 , r , j g_{l,r,j}=g_{l,mid,j}+g_{mid+1,r,j} gl,r,j=gl,mid,j+gmid+1,r,j

那么,最后的答案即为 m i n ( f 1 , n , 1 , f 1 , n , 2 , . . . , f 1 , n , x ) min(f_{1, n, 1}, f_{1, n, 2}, ..., f_{1, n, x}) min(f1,n,1,f1,n,2,...,f1,n,x)

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const LL mod = 998244353;
const LL N = 155;
int n, x, a[N], f[N][N][N], g[N][N][N], tmp[N][N][N];

void solve() {
    cin >> n >> x;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        for (int j = 1; j <= x; j++) {
            if (j != a[i]) {
                g[i][i][j] = 0;
                f[i][i][j] = 1;
            }
        }
        g[i][i][a[i]] = 1;
        f[i][i][a[i]] = 0;
    }
    for (int len = 2; len <= n; len++) {
        for (int l = 1; l + len - 1 <= n; l++) {
            int r = l + len - 1;
            for (int j = 1; j <= x; j++) {
                for (int mid = l; mid < r; mid++) {
                    f[l][r][j] = min(f[l][r][j], f[l][mid][j] + f[mid + 1][r][j]);
                    tmp[l][r][j] = min(tmp[l][r][j], g[l][mid][j] + g[mid + 1][r][j]);
                }
                f[l][r][j] = min(f[l][r][j], tmp[l][r][j] + 1);
                for (int k = 1; k <= x; k++) {
                    if (k == j) {
                        continue;
                    }
                    g[l][r][k] = min(g[l][r][k], tmp[l][r][j] + 1);
                }
            }
            for (int j = 1; j <= x; j++) {
                g[l][r][j] = min(g[l][r][j], tmp[l][r][j]);
            }
        }
    }
    int ans = n;
    for (int i = 1; i <= x; i++) {
        ans = min(ans, f[1][n][i]);
    }
    cout << ans << endl;
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        memset(f, 0x3f, sizeof(f));
        memset(g, 0x3f, sizeof(g));
        memset(tmp, 0x3f, sizeof(tmp));
        solve();
    }
    return 0;
}

学习交流

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

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

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

相关文章

用户体验革命:Facebook如何重新定义社交交互

在数字化的时代&#xff0c;社交媒体不仅仅是连接人与人之间的桥梁&#xff0c;更是用户体验不断演进的舞台。Facebook&#xff0c;作为全球最大的社交媒体平台之一&#xff0c;一直在努力通过创新和技术提升&#xff0c;重新定义社交交互&#xff0c;为用户带来更加丰富、便捷…

机器人DH建模

D-H 根据表达式判断所建立的DH模型是标准型&#xff08;Standard DH&#xff09;还是改进型&#xff08;Modified DH&#xff09; 第三四行的首元素为0的是标准型&#xff0c;参考博客 标准DH参数坐标系建立在传动轴上&#xff0c;而修正DH参数坐标系建立在驱动轴上。修正D…

二维码地址门牌管理系统:预约安全、智能生活

文章目录 前言一、访客预约功能二、安全性保障三、智慧小区生活 前言 二维码地址门牌管理系统的出现不仅提升了小区的安全性&#xff0c;还为访客提供了更便捷的预约服务&#xff0c;让亲朋好友轻松进入小区。 一、访客预约功能 该系统提供了访客预约功能&#xff0c;业主可为…

Spark UI中 Shuffle Exchange 和 BroadcastExchange 中的 dataSize 值为什么不一样

背景 Spark 3.5 最近在看Spark UI 上的一些指标看到一个很有意思的东西, 相邻的Shuffle Exechange 和 BroadcastExechange 中的 datasize 居然不一样&#xff0c; 前者为 765KB, 后者为 64.5MB。差别还不少&#xff0c;中间就增加了一个 AQEShuffleRead 计划 结论 Shuffle E…

c语言:链表

链表的大致思维导图&#xff1a; 链表的相关概念和解释&#xff1a; 节点&#xff08;Node&#xff09;&#xff1a;链表中的每个元素都是一个节点&#xff0c;节点包含数据和指向下一个节点的指针。 头节点&#xff08;Head Node&#xff09;&#xff1a;链表的第一个节点称…

【动态规划】879. 盈利计划

作者推荐 【动态规划】【广度优先搜索】【状态压缩】847 访问所有节点的最短路径 本文涉及知识点 动态规划汇总 LeetCode879. 盈利计划 集团里有 n 名员工&#xff0c;他们可以完成各种各样的工作创造利润。 第 i 种工作会产生 profit[i] 的利润&#xff0c;它要求 group[…

在linux部署Prometheus+Grafana+Exporter监控系统性能

Prometheus、Grafana和Report组件是什么&#xff1f; Prometheus、Grafana和Exporter是常用于系统监控和指标收集的组合。 Prometheus是一种开源的系统监控和警报工具。它可以收集各种指标数据&#xff0c;并提供强大的查询语言和灵活的警报规则&#xff0c;用于实时监控系统…

[框架系列]-[通用lock框架]集成及具体配置使用

目录 一&#xff1a;框架集成 1.添加pom依赖 2.开启lock配置 二&#xff1a;配置详细介绍 1.配置清单 2.具体配置介绍 &#xff08;1&#xff09;implementer &#xff08;2&#xff09;type &#xff08;3&#xff09;transactionStrategy &#xff08;4&#xff09…

利用大模型审合同真的可以吗?

#大模型 #大模型审合同 最近有很多朋友留言&#xff0c;询问关于大模型审合同的问题&#xff0c;今天就小智一起来探讨下这个问题。 &#xff08;智合同-采用深度学习、自然语言处理技术、知识图谱等人工智能技术&#xff0c;为企业提供专业的合同相关的智能服务。其服务包含…

【Java IO】设计模式 (装饰者模式)

Java I/O 使用了装饰者模式来实现。 装饰者模式 请参考装饰者模式详解 装饰者(Decorator)和具体组件(ConcreteComponent)都继承自组件(Component)&#xff0c;具体组件的方法实现不需要依赖于其它对象&#xff0c;而装饰者组合了一个组件&#xff0c;这样它可以装饰其它装饰者…

Excel数据检索省力小工具(文末附源码)

Excel数据检索省力小工具&#xff08;文末附源码&#xff09; 引言 ​ 相信很多人都是用过VLOOKUP函数来检索和处理Excel数据。比如教师查看班级学生成绩表&#xff0c;想单独检索某个科目、某个学生&#xff0c;某一分数段&#xff08;80~90分数段内的成绩&#xff09;&…

网络安全基础概念

目录 网络安全背景 网络空间安全 --- Cyberspace 常见的网络安全术语 协议栈自身的脆弱性&#xff1a; 常见安全风险&#xff1a; 物理层--物理攻击 物理设备窃听&#xff1a; 链路层-- MAC洪泛攻击&#xff1a; 链路层--ARP欺骗 网络层--ICMP攻击 传输层--TCP SYN Flood攻击: …

信息检索与数据挖掘 | (八)语言建模的IR

文章目录 &#x1f4da;语言生成模型&#x1f4da;平滑&#x1f407;线性插值平滑方法(Lelinek-Mercer)&#x1f407;dirichlet 平滑&#x1f407;Vector space&#xff08;向量空间&#xff09; vs BM25 vs LM &#x1f4da;语言生成模型 传统的语言生成模型可以用于识别或生成…

南京观海微电子---时序分析基本概念(二)——保持时间

1. 概念的理解 以上升沿锁存为例&#xff0c;保持时间&#xff08;Th&#xff09;是指在触发器的时钟信号上升沿到来以后&#xff0c;数据稳定不变的时间。如下图所示&#xff0c;一个数据要在上升沿被锁存&#xff0c;那么这个数据需要在时钟上升沿到来后的保持时间内保持稳定…

展会日记:ICCAD2023,Samtec连接器无处不在

【序言】 “作为重要的电子元器件&#xff0c;连接器在如今的数字与现实世界中&#xff0c;扮演了不可或缺的角色。Samtec作为全球知名的连接器厂商&#xff0c;在芯片到板、板到板、射频、光模块等领域都有着卓越表现~ 今年&#xff0c;我们更是将这种存在感在2023 ICCAD上&a…

Nginx 基础使用

目录结构 进入Nginx的主目录我们可以看到这些文件夹 client_body_temp conf fastcgi_temp html logs proxy_temp sbin scgi_temp uwsgi_temp其中这几个文件夹在刚安装后是没有的&#xff0c;主要用来存放运行过程中的临时文件 client_body_temp fastcgi_temp proxy_temp scg…

uniapp中打包Andiord app,在真机调试时地图以及定位功能可以正常使用,打包成app后失效问题(高德地图)

踩坑uniapp中打包Andiord app&#xff0c;在真机调试时地图以及定位功能可以正常使用&#xff0c;打包成app后失效问题_uniapp真机调试高德地图正常 打包apk高德地图就不加载-CSDN博客 问题&#xff1a; 目前两个项目&#xff0c;一个项目是从另一个项目里面分割出来的一整套…

华为云磁盘性能指标(参考)

MD[华为云磁盘性能指标(参考)] 云硬盘&#xff08;Elastic Volume Service, EVS&#xff09; 根据性能&#xff0c;磁盘可分为极速型SSD V2、极速型SSD、通用型SSD V2、超高IO、通用型SSD、高IO、普通IO。 性能指标(参考)&#xff0c;测速说明&#xff1a;操作系统-windows …

共襄Agent智能体盛举,实在智能2024生态伙伴大会杭州站圆满收官!

1月19日&#xff0c;以“实在Agent智能体”为主题的「2024实在智能生态伙伴大会&#xff08;杭州站&#xff09;」在杭州人工智能小镇隆重启幕&#xff01; 中国电信/联通/中海油等数十家央企子公司领导代表、天翼数科/华为/浪潮/统信/贝锐/vivo集团/新华三/中软国际/中投创展/…

华为AC+FIT AP组网配置

AC配置 vlan batch 100 to 101dhcp enableip pool apgateway-list 192.168.100.254 network 192.168.100.0 mask 255.255.255.0 interface Vlanif100ip address 192.168.100.254 255.255.255.0dhcp select globalinterface GigabitEthernet0/0/1port link-type trunkport trun…