Educational Codeforces Round 69
Contest Info
[Practice Link](https://codeforc.es/contest/1197)
Solved | A | B | C | D | E | F |
---|---|---|---|---|---|---|
5/6 | O | O | O | O | Ø | - |
- O 在比赛中通过
- Ø 赛后通过
- ! 尝试了但是失败了
- - 没有尝试
Solutions
A. DIY Wooden Ladder
签到题。
#include <bits/stdc++.h>
using namespace std;
#define N 100010
int n, a[N];
int main() {
int T; scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", a + i);
sort(a + 1, a + 1 + n);
int res = 0;
for (int i = 2; i < n; ++i) {
res = max(res, min(a[i] - 1, i - 1));
}
printf("%d\n", res);
}
return 0;
}
B. Pillars
题意:
有\(n\)根柱子,每根柱子上有一个磁盘,一个磁盘能从第\(i\)根柱子移动到第\(j\)根柱子的前提是:
- 第\(j\)根柱子上没有磁盘
- 或者第\(i\)根柱子上的磁盘半径颜色小于第\(j\)根柱子的磁盘
现在给出每根柱子上磁盘的半径,问能够存在一种方案使得将所有的磁盘都移动的一根柱子上
思路:
考虑假设能将所有磁盘移动到一根柱子上,那么最终肯定是移动到初始磁盘半径最大的那根柱子上。
那么考虑从这个柱子开始,每次往两边扩展,取大的贪心往这根柱子上移动。
如果不能移动就是不行。
因为考虑最后那根柱子上的磁盘半径肯定是递增的,所以不可能存在跨越移动的情况。
代码:
#include <bits/stdc++.h>
using namespace std;
#define N 200010
int n, a[N];
int main() {
while (scanf("%d", &n) != EOF) {
for (int i = 1; i <= n; ++i) scanf("%d", a + i);
int pos = 1;
for (int i = 2; i <= n; ++i) {
if (a[i] > a[pos]) pos = i;
}
int l = pos - 1, r = pos + 1;
bool F = 1;
int lst = a[pos];
while (l >= 1 || r <= n) {
if (l < 1) {
if (a[r] >= lst) {
F = 0;
break;
}
lst = a[r];
++r;
} else if (r > n) {
if (a[l] >= lst) {
F = 0;
break;
}
lst = a[l];
--l;
} else {
if (a[l] > a[r]) {
if (a[l] >= lst) {
F = 0;
break;
}
lst = a[l];
--l;
} else {
if (a[r] >= lst) {
F = 0;
break;
}
lst = a[r];
++r;
}
}
}
puts(F ? "YES" : "NO");
}
return 0;
}
C. Array Splitting
题意:
有一个长度为\(n\)的序列\(a_i\),要将序列分成\(k\)段,使得下式最小:
\sum\limits_{i = 1}^k (max(i) - min(i))
\end{eqnarray*}
\]
其中\(max(i)\)表示第\(i\)段中最大的数,\(min(i)\)表示第\(i\)段中最小的数,保证\(a_i\)是单调非降序的。
思路:
考虑\(a_i\)是单调非降的,那么\(max(i) - min(i)\)这个东西肯定是区间的末尾减去区间的开头,那么注意到区间的末尾的下一个数即为下一个区间的开头,变换式子有:
a_n - a_1 + \sum\limits_{i = 1}^{k - 1} a_{b_i} - a_{b_i + 1}
\end{eqnarray*}
\]
其中\(b_i\)表示第\(i\)段末尾的下标。
然后这个东西用堆维护一下,贪心取\(k - 1\)个即可。
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 300010
int n, k, a[N];
int main() {
while (scanf("%d%d", &n, &k) != EOF) {
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
}
ll res = a[n] - a[1];
vector <int> vec;
for (int i = 1; i < n; ++i) {
vec.push_back(a[i] - a[i + 1]);
}
sort(vec.begin(), vec.end());
for (int i = 0; i < k - 1; ++i) {
res += vec[i];
}
printf("%lld\n", res);
}
return 0;
}
D. Yet Another Subarray Problem
题意:
有一个序列\(a_i\),定义一个子区间的价值:
\sum\limits_{i = l}^r a_i - k \left\lceil \frac{r - l + 1}{m} \right\rceil
\end{eqnarray*}
\]
问所有子区间中最大的价值是多少?
思路:
维护一个前缀和\(S\),那么变换式子有:
S_r - S_l - k \left\lceil \frac{r - l}{m} \right\rceil
\end{eqnarray*}
\]
我们希望将\(\left\lceil \frac{r - l}{m} \right\rceil\)拆开成\(\left\lceil \frac{r}{m} \right\rceil - \left\lceil \frac{l}{m} \right\rceil\),但是这样是不行的。
注意到\(m\)很小,所以可以通过分类讨论一下将\(\left\lceil \frac{x}{m} \right\rceil\)按\(x \bmod m\)进行分类,然后讨论一下合并即可。
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 300010
int n, m, k;
ll a[N];
ll f[20];
int main() {
while (scanf("%d%d%d", &n, &m, &k) != EOF) {
for (int i = 1; i <= n; ++i) scanf("%lld", a + i);
ll res = 0;
for (int i = 0; i < m; ++i) f[i] = 0;
f[0] = -k;
for (int i = 1; i <= n; ++i) {
a[i] += a[i - 1];
for (int j = 0; j < m; ++j) {
if (m - i % m >= m - j) {
res = max(res, a[i] - f[j] - 1ll * k * (i / m + 1));
} else {
res = max(res, a[i] - f[j] - 1ll * k * (i / m + 2));
}
}
f[i % m] = min(f[i % m], a[i] - 1ll * k * (i / m + 1));
}
printf("%lld\n", res);
}
return 0;
}
E. Culture Code
题意:
有\(n\)个俄罗斯套娃,每个套娃有内径\(in_i\)和外径\(out_i, out_i > in_i\),一个套娃\(i\)能套在套娃\(j\)里面,当且仅当\(out_i \leq in_j\)。
定义一组套在的额外空间为
in_1 + (in_2 - out_1) + (in_3 - out_3) + \cdots + (in_k - out_{k - 1})
\end{eqnarray*}
\]
其中\(in_k\)为最外成那个套娃的内径。
定义一组套娃是个极大套娃组:当且仅当不能再有另外一个套娃套在他们身上了。
询问有多少种极大套娃组的额外空间最小。
思路:
先将套娃分成两类:
- 第一类:没有另外一个套娃能套在它头上
- 第二类:至少存在一个套娃能够套在它头上
那么考虑把方案数全都算在第一类套娃头上。
那么先将所有套娃按内径从小到大排序,那么定义\(f[i]\)表示第\(i\)个套娃产生最小额外空间时的方案数,那么它能从第\(j\)个套娃转移过来当且仅当第\(out_j <= in_i\)。
那么再考虑变换额外空间的式子:
in_k + \sum\limits_{i = 1}^{k - 1} out_i - in_i
\end{eqnarray*}
\]
这样就变成了极大套娃组的额外空间中除了第一个套娃,其他套娃的贡献独立,为\(out_i - in_i\)。
那么转移的时候维护一下最小额外空间,如果最小额外空间相同就合并方案数,否则更新方案数。
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define INFLL 0x3f3f3f3f3f3f3f3f
#define N 400010
#define pii pair <ll, ll>
#define fi first
#define se second
const ll p = 1e9 + 7;
int n, tot;
pii a[N];
int b[N];
ll c[N], d[N];
struct SEG {
struct node {
ll Min, sum;
node() {
sum = 0;
Min = INFLL;
}
node(ll Min, ll sum) : Min(Min), sum(sum) {}
node operator + (const node &other) const {
node res = node();
if (Min == other.Min) {
res.Min = Min;
res.sum = (sum + other.sum) % p;
} else if (Min < other.Min) {
res.Min = Min;
res.sum = sum;
} else {
res.Min = other.Min;
res.sum = other.sum;
}
return res;
}
}t[N << 2], res;
void build(int id, int l, int r) {
t[id] = node();
if (l == r) return;
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
}
void update(int id, int l, int r, int pos, node x) {
if (l == r) {
t[id] = t[id] + x;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) update(id << 1, l, mid, pos, x);
else update(id << 1 | 1, mid + 1, r, pos, x);
t[id] = t[id << 1] + t[id << 1 | 1];
}
void query(int id, int l, int r, int ql, int qr) {
if (l >= ql && r <= qr) {
res = res + t[id];
return;
}
int mid = (l + r) >> 1;
if (ql <= mid) query(id << 1, l, mid, ql, qr);
if (qr > mid) query(id << 1 | 1, mid + 1, r, ql, qr);
}
}seg;
int id(int x) {
return lower_bound(b + 1, b + 1 + tot, x) - b;
}
int main() {
while (scanf("%d", &n) != EOF) {
tot = 0;
for (int i = 1; i <= n; ++i) scanf("%lld%lld", &a[i].fi, &a[i].se);
for (int i = 1; i <= n; ++i) {
b[++tot] = a[i].fi;
b[++tot] = a[i].se;
}
sort(b + 1, b + 1 + tot);
tot = unique(b + 1, b + 1 + tot) - b - 1;
sort(a + 1, a + 1 + n, [](pii x, pii y) {
if (x.se != y.se) return x.se < y.se;
return x.fi > y.fi;
});
ll Min = INFLL;
ll res = 0;
seg.build(1, 1, tot);
for (int i = 1; i <= n; ++i) {
seg.res = SEG::node();
seg.query(1, 1, tot, 1, id(a[i].se));
if (seg.res.Min == INFLL) {
seg.res = SEG::node(-a[i].fi + a[i].se, 1);
seg.update(1, 1, tot, id(a[i].fi), seg.res);
c[i] = a[i].se;
d[i] = 1;
} else {
c[i] = a[i].se + seg.res.Min;
d[i] = seg.res.sum;
seg.res.Min += -a[i].fi + a[i].se;
seg.update(1, 1, tot, id(a[i].fi), seg.res);
}
if (a[i].fi > a[n].se) {
Min = min(Min, c[i]);
}
}
for (int i = 1; i <= n; ++i) {
if (a[i].fi > a[n].se && c[i] == Min) {
res = (res + d[i]) % p;
}
}
printf("%lld\n", res);
}
return 0;
}
Educational Codeforces Round 69的更多相关文章
- Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code
Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code 题目链接 题意: 给出\(n\)个俄罗斯套娃,每个套娃都有一个\( ...
- Educational Codeforces Round 69 D. Yet Another Subarray Problem
Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 题目链接 题意: 求\(\sum_ ...
- Educational Codeforces Round 69 D E
Educational Codeforces Round 69 题解 题目编号 A B C D E F 完成情况 √ √ √ ★ ★ - D. Yet Another Subarray Problem ...
- Educational Codeforces Round 69 (Rated for Div. 2)
A. DIY ...
- Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 背包dp
D. Yet Another Subarray Problem You are given an array \(a_1, a_2, \dots , a_n\) and two integers \( ...
- Educational Codeforces Round 69 (Rated for Div. 2) C. Array Splitting 水题
C. Array Splitting You are given a sorted array
- Educational Codeforces Round 69 (Rated for Div. 2) A~D Sloution
A. DIY Wooden Ladder 题意:有一些不能切的木板,每个都有一个长度,要做一个梯子,求梯子的最大台阶数 做梯子的木板分为两种,两边的两条木板和中间的若干条台阶木板 台阶数为 $k$ 的 ...
- Educational Codeforces Round 69 E - Culture Code (最短路计数+线段树优化建图)
题意:有n个空心物品,每个物品有外部体积outi和内部体积ini,如果ini>outj,那么j就可以套在i里面.现在我们要选出n个物品的一个子集,这个子集内的k个物品全部套在一起,且剩下的物品都 ...
- Educational Codeforces Round 69 (Rated for Div. 2)D(DP,思维)
#include<bits/stdc++.h>using namespace std;int a[300007];long long sum[300007],tmp[300007],mx[ ...
随机推荐
- 【LEETCODE】36、121题,Best Time to Buy and Sell Stock
package y2019.Algorithm.array; /** * @ProjectName: cutter-point * @Package: y2019.Algorithm.array * ...
- 在vue中使用swiper组件
第一步:在终端的项目根目录下载安装swiper: cnpm/npm install vue-awesome-swiper --save; 第二步:在程序入口文件main.js中引用: import V ...
- Student's Camp CodeForces - 708E (dp,前缀和优化)
大意: $n$行$m$列砖, 白天左侧边界每块砖有$p$概率被摧毁, 晚上右侧边界有$p$概率被摧毁, 求最后上下边界连通的概率. 记${dp}_{i,l,r}$为遍历到第$t$行时, 第$t$行砖块 ...
- linux主机内存告警shell脚本
#!/bin/sh ramusage=$(free | awk '/Mem/{printf("RAM Usage: %.2f\n"), $3/$2*100}'| awk '{pri ...
- Gogs + Drone 实现CI/CD(CD)
前文已经实现CI部分,本文继续以Asp.Net Core实现CD部分. 创建gogs仓库 首先在gogs创建一个空项目drone-ci-demo,本地新建一个asp.net core项目,并且在与.c ...
- 关于Ad-hoc
Ad-hoc是wifi的一个模式,依托普通无线局域网802.11家族.网络中所有结点的地位平等,无需设置任何的中心控制结点,省去了无线中介设备AP.比如一台电脑建立了一个网络,这个时候加入了两台电脑. ...
- JavaScript中进制和字符编码问题
1.进制: JavaScript中允许使用字面量的形式声明不同进制的数字: var a = 0b10; // 2 声明一个二进制 var b = 010; // 8 八进制,严格模式下会报错 var ...
- javascript_09-数组
数组 //数组 // var array = new Array(); // array[0]="zs"; // array[1]="ls"; var name ...
- 缓存数据库memcache、redis原理对比
一.问题: 数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求. 二.解决方案: 1.通过高速服务器Cache缓存数据库数据 2.内存数据库 (这里 ...
- java - day018 - 线程续
生产者,消费者 线程间的通信模型 等待和通知 在生产者和消费者模型中 消费者暂停等待数据 生产者产生数据后发出通知 object 方法 wait(); notify(); 通知一个 notifyAll ...