比赛链接

A

题意

有两座塔由红蓝方块组成,分别有 \(n,m\) 个方块,一次操作可以把一座塔塔顶的方块移动到另一座塔的塔顶,问通过操作是否能使每座塔中没有颜色相同的相邻方块。

题解

知识点:贪心。

注意到,操作最多能拆掉一对相邻的方块,因此统计两座塔不合法的对数。

  1. 如果超过 \(1\) 对,那么无解。
  2. 如果只有 \(1\) 对,那么操作一定使得塔顶相对,塔顶若颜色一样就无解,否则有解。
  3. 如果没有不合法的方块,也有解。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long; bool solve() {
int n, m;
cin >> n >> m;
string s, t;
cin >> s >> t;
int mis = 0;
for (int i = 1;i < n;i++) if (s[i] == s[i - 1]) { mis++; }
for (int i = 1;i < m;i++) if (t[i] == t[i - 1]) { mis++; }
if (mis >= 2 || mis == 1 && s.back() == t.back()) return false;
else cout << "YES" << '\n';
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << "NO" << '\n';
}
return 0;
}

B

题意

坐标轴上覆盖了 \(n\) 个线段,指定一个点坐标为 \(k\) ,能否通过删除一些线段使得覆盖指定点的线段严格最多。

题解

知识点:贪心。

直接去除没有覆盖 \(k\) 的线段,此时若 \(k\) 覆盖数严格最多,那么有解;否则,去除任意一条线段,都会使 \(k\) 和一些点同时减 \(1\) ,不会使得 \(k\) 覆盖数严格最多,所以无解。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long; bool solve() {
int n, k;
cin >> n >> k;
vector<int> vis(57);
for (int i = 1;i <= n;i++) {
int l, r;
cin >> l >> r;
if (l <= k && k <= r) vis[l]++, vis[r + 1]--;
}
for (int i = 1;i <= 50;i++) vis[i] += vis[i - 1];
bool ok = 1;
for (int i = 1;i <= 50;i++) if (i != k) ok &= vis[k] > vis[i];
if (ok) cout << "YES" << '\n';
else return false;
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << "NO" << '\n';
}
return 0;
}

C

题意

有 \(n\) 杯茶,第 \(i\) 杯茶有 \(a_i\) 毫升。有 \(n\) 个人,每个人每次最多能喝 \(b_i\) 毫升。

第一轮,第 \(i\) 个人喝第 \(i\) 杯茶,第 \(i\) 杯茶减少 \(\min(a_i,b_i)(1\leq i\leq n)\) 毫升。

第二轮,第 \(i\) 个人喝第 \(i-1\) 杯茶,第 \(1\) 个人不喝,第 \(i\) 杯茶减少 \(\min(a_i,b_{i+1})(1\leq i\leq n-1)\) 毫升。

以此类推,问最后每个人喝了多少毫升茶。

题解

知识点:枚举,前缀和,差分,二分。

考虑枚举每杯茶的贡献。第 \(i\) 杯茶会被 \([i,n]\) 内的人喝,但茶会被喝完,所以设 \(sumb\) 为 \(b\) 的前缀和,找到最大的位置 \(j\) 满足 \(sumb_j - sumb_{i-1}\leq a_i \iff sum_{j} \leq sum_{i-1} + a_i\) ,即 \([i,j]\) 的人能喝到自己的上限,第 \(j+1\) 个人能喝到剩下的 \(a_i - (sum_j - sum_{i-1})\) 。

我们用差分数组 \(cnt\) 完成 \([i,j]\) 的区间加 \(1\) ,最后前缀和就能得到第 \(i\) 个人能喝到自己的上限多少次。再用数组 \(delta\) 记录第 \(i\) 个人喝了多少剩下的茶,最后 \(cnt_ib_i + delta_i\) 即第 \(i\) 个人的毫升数。

时间复杂度 \(O(n\log n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long; int a[200007], b[200007];
ll sumb[200007];
int cnt[200007];
ll delta[200007];
bool solve() {
int n;
cin >> n;
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++) sumb[i] = sumb[i - 1] + b[i], delta[i] = 0, cnt[i] = 0;
for (int i = 1;i <= n;i++) {
int id = upper_bound(sumb + i, sumb + n + 1, a[i] + sumb[i - 1]) - sumb - 1;
cnt[i]++;
cnt[id + 1]--;
delta[id + 1] += a[i] - (sumb[id] - sumb[i - 1]);
}
for (int i = 1;i <= n;i++) {
cnt[i] += cnt[i - 1];
cout << 1LL * cnt[i] * b[i] + delta[i] << ' ';
}
cout << '\n';
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}

D

题意

给定一个有 \(n\) 个点 \(n\) 条边的无向带权图,保证 \(n\) 为 \(6\) 的倍数,组成 \(\dfrac{n}{3}\) 个三元环: \((1,2,3),(4,5,6),\cdots\) 。

现在给每个点染上红或蓝两种颜色,要求红色有 \(\dfrac{n}{2}\) 个点、蓝色也有 \(\dfrac{n}{2}\) 个点 。

定义一种染色方案的价值为,两端颜色不同的边的权值总和。

设所有染色方案种价值最大为 \(W\) ,问有多少种染色方案的价值为 \(W\) 。

题解

知识点:贪心,排列组合。

显然,一个三元环的最多能贡献两条边,即两红一蓝或两蓝一红,刚好我们可以使得所有三元环都能贡献出两条边,我们对每个三元环贪心地选最大的两条边即可达到最大价值。因此,染色方案必然是每个三元环两红一蓝或两蓝一红,且最大的两条边端点颜色不同。

考虑三元环的分配方案,我们需要一半的两红一蓝另一半两蓝一红,因此方案数是 \(\dbinom{n/3}{n/6}\) 。再考虑每一种分配方案的不同染色方案,显然三边权值相同的三元组能贡献三种方案,而两边权值相同的三元组当且仅当三边中不同的权值是最大值时会贡献两种方案,分别记为 \(cnt_1,cnt_2\) ,则总方案数为 \(3^{cnt_1} \cdot 2^{cnt_2}\cdot \dbinom{n/3}{n/6}\) 。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long; const int P = 998244353;
const int N = 3e5 + 7;
namespace CNM {
int qpow(int a, ll k) {
int ans = 1;
while (k) {
if (k & 1) ans = 1LL * ans * a % P;
k >>= 1;
a = 1LL * a * a % P;
}
return ans;
} int fact[N], invfact[N];
void init(int n) {
fact[0] = 1;
for (int i = 1;i <= n;i++) fact[i] = 1LL * i * fact[i - 1] % P;
invfact[n] = qpow(fact[n], P - 2);
for (int i = n;i >= 1;i--) invfact[i - 1] = 1LL * invfact[i] * i % P;
} int C(int n, int m) {
if (n == m && m == -1) return 1; //* 隔板法特判
if (n < m || m < 0) return 0;
return 1LL * fact[n] * invfact[n - m] % P * invfact[m] % P;
}
} int w[300007];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
CNM::init(n / 3);
for (int i = 1;i <= n;i++) cin >> w[i];
int cnt1 = 0, cnt2 = 0;
for (int i = 3;i <= n;i += 3) {
if (w[i - 2] == w[i - 1] && w[i - 1] == w[i]) cnt1++;
else if (w[i] == w[i - 1] || w[i - 1] == w[i - 2] || w[i - 2] == w[i]) {
int mx = max({ w[i - 2],w[i - 1],w[i] });
if (count(w + i - 2, w + i + 1, mx) == 1) cnt2++;
}
}
cout << 1LL * CNM::qpow(3, cnt1) * CNM::qpow(2, cnt2) % P * CNM::C(n / 3, n / 6) % P << '\n';
return 0;
}

E

题意

有 \(n\) 个怪物,第 \(i\) 个怪物的血量有 \(h_i\) ,血量降为 \(0\) 时立刻死亡,你有两种攻击方式:

  1. 指定一个怪物,对其普通攻击,造成 \(1\) 点伤害,消耗 \(1\) 点魔法。普通攻击可以使用无限次。

  2. 指定一个怪物,对其释放爆炸魔法,造成的伤害取决于注入的魔法,如果想要消耗 \(x\) 点魔法注入其中,会造成 \(x\) 点伤害。

    爆炸魔法具有连锁性,如果被魔法击中的怪物死了,假设是第 \(i\) 个怪物,那么 \(i-1,i+1\) 两个怪物会受到 \(h_i-1\) 的伤害,以此类推,直至没有怪物死掉。这个魔法只能使用一次。

问,最少需要多少魔法能消灭所有怪物。

题解

知识点:枚举,贪心,单调栈。

显然,我们可以枚举释放爆炸魔法的位置,取造成伤害最多的即可。

对于每个位置,都可以向两侧扩展,不妨先考虑左侧部分。

我们设 \(l_i\) 为在第 \(i\) 个位置释放爆炸魔法后,左侧(包括自己)能造成的最大伤害。我们考虑在 \(i\) 处依次向左扩展的两种情况:

  1. 对于 \(j<i\) ,若 \(h_j \geq h_i - (i-j)\) ,则说明 \(j\) 不能被消灭,但我们可以在之前通过普通攻击把血量降到可以消灭的血量,因此还是可以造成 \(h_i-(i-j)\) 的伤害。
  2. 对于 \(j<i\) ,一旦出现 \(h_j < h_i-(i-j)\) ,则说明 \(j\) 虽然能被消灭,但会降低之后的魔法伤害,后续计算会由 \(h_j\) 直接支配,我们通过 \(l_i\) 直接转移即可,并停止扩展。

注意到,如此操作的复杂度是平方的,我们考虑优化复杂度。我们可以将条件中的变量转换为 \(h_j - j,h_i -i\) ,就可以绑定成一个值了。我们发现,满足情况1造成的伤害都是连续减 \(1\) 的,而满足情况 \(2\) 后直接加 \(f_j\) 后停止,所以我们只要求左侧第一个满足 \(h_j - j < h_i-i\) 的位置 \(j\) ,就可以直接得到造成的伤害 \(l_j + \dfrac{(i-j)(h_i-(i-j)+1 + h_i)}{2}\) 。

显然,这个过程可以用单调递增栈实现的,其可以维护一个字典序最小的极长递增子序列(极长递增子序列指,一个不能继续递增的递增子序列),而子序列相邻两元素之间的在原数组的其他元素,一定都大于等于这两个元素,因此是不需要比较的。于是,对于一个值,我们比较维护的子序列,就可以跳过一些不需要比较的位置。整个过程,每个元素只会出入一次维护的子序列,因此复杂度是线性的。

对于右侧,我们把 \(h\) 反转,重新算一遍 \(h_i-i\) 做相同的事情得到 \(r_i\) ,再将 \(r_i\) 反转,\(h\) 复原。最后,设血量总和为 \(sum\) ,枚举每个位置 \(i\) 得到 \(sum - (l_i + r_i - h_i) + h_i\) 取最小值。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long; int n;
int h[300007], hi[300007];
ll l[300007], r[300007];
void calc(ll *f) {
stack<int> stk;
stk.push(0);
for (int i = 1;i <= n;i++) {
while (stk.size() > 1 && hi[stk.top()] >= hi[i]) stk.pop();
int len = min(h[i], i - stk.top());
f[i] = f[stk.top()] + 1LL * len * (h[i] + (h[i] - len + 1)) / 2;
stk.push(i);
}
} bool solve() {
cin >> n;
ll sum = 0;
for (int i = 1;i <= n;i++) cin >> h[i], sum += h[i]; for (int i = 1;i <= n;i++) hi[i] = h[i] - i;
calc(l); reverse(h + 1, h + n + 1);
for (int i = 1;i <= n;i++) hi[i] = h[i] - i;
calc(r); reverse(h + 1, h + n + 1);
reverse(r + 1, r + n + 1);
ll ans = 1e18;
for (int i = 1;i <= n;i++) ans = min(ans, sum - (l[i] + r[i] - h[i]) + h[i]);
cout << ans << '\n';
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}

Educational Codeforces Round 143 (Rated for Div. 2) A-E的更多相关文章

  1. Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...

  2. Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...

  3. Educational Codeforces Round 43 (Rated for Div. 2)

    Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...

  4. Educational Codeforces Round 35 (Rated for Div. 2)

    Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...

  5. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...

  6. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...

  7. Educational Codeforces Round 63 (Rated for Div. 2) 题解

    Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...

  8. Educational Codeforces Round 39 (Rated for Div. 2) G

    Educational Codeforces Round 39 (Rated for Div. 2) G 题意: 给一个序列\(a_i(1 <= a_i <= 10^{9}),2 < ...

  9. Educational Codeforces Round 48 (Rated for Div. 2) CD题解

    Educational Codeforces Round 48 (Rated for Div. 2) C. Vasya And The Mushrooms 题目链接:https://codeforce ...

  10. Educational Codeforces Round 60 (Rated for Div. 2) 题解

    Educational Codeforces Round 60 (Rated for Div. 2) 题目链接:https://codeforces.com/contest/1117 A. Best ...

随机推荐

  1. 你听说过OTA吗?

    以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「englyf」https://mp.weixin.qq.com/s/M660Sc4ey1SxCpRT6vcM9g what? 不知有多少 ...

  2. 【iOS逆向】某茅台App算法分析还原

    1.目标 某茅台软件的actParam算法分析还原. 2.使用工具 mac系统 frida-ios-dump:砸壳 已越狱iOS设备:脱壳及frida调试 IDA Pro:静态分析 Charles:抓 ...

  3. 【云原生 · Kubernetes】Kubernetes 编排部署GPMall(一)

    1.规划节点 IP 主机名 节点 10.24.2.156 master Kubernetes master 节点 10.24.2.157 node Kubernetes worker 节点 2.基础准 ...

  4. Duplicate property mapping of xxx found in xx 嵌套异常,重复的属性在映射中发现。

    该异常的原意是因为在映射文件中出现了两个一样的属性名: <property name="相同的属性名出现了两次以上" > <property name=" ...

  5. HTTP2 协议长文详解

    一.HTTP2 简介 HTTP2 是一个超文本传输协议,它是 HTTP 协议的第二个版本.HTTP2 主要是基于 google 的 SPDY 协议,SPDY 的关键技术被 HTTP2 采纳了,因此 S ...

  6. 【Shell案例】【awk、grep、sort、uniq】10、第二列是否有重复

    给定一个 nowcoder.txt文件,其中有3列信息,如下实例,编写一个shell脚本来检查文件第二列是否有重复,且有几个重复,并提取出重复的行的第二列信息:实例:20201001 python 9 ...

  7. C++四舍五入并且保留7为小数

    问题描述给定圆的半径r,求圆的面积.输入格式输入包含一个整数r,表示圆的半径.输出格式输出一行,包含一个实数,四舍五入保留小数点后7位,表示圆的面积.说明:在本题中,输入是一个整数,但是输出是一个实数 ...

  8. 痞子衡嵌入式:存储器大厂Micron的NOR Flash芯片特殊丝印设计(FBGA代码)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是存储器大厂Micron的NOR Flash芯片特殊丝印设计(FBGA代码). 痞子衡之前写过一篇文章 <J-Flash在Micron ...

  9. P1024 [NOI2001] 食物链【种类并查集】

    题意 P1024 简化题意:给定 \(n\) 和 \(k(n\leqslant5\times10^4,k\leqslant10^5)\) ,表示有 \(n\) 个动物, \(k\) 个描述,其中: \ ...

  10. [编程基础] C++多线程入门8-从线程返回值

    原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++11标准. 8 从线程返回值 8 ...