Contest Info


[Practice Link](https://codeforces.com/contest/1252)

Solved A B C D E F G H I J K L
7/12 O - O - O - O O - O O -
  • O 在比赛中通过
  • Ø 赛后通过
  • ! 尝试了但是失败了
  • - 没有尝试

Solutions


A. Copying Homework

签到。

C. Even Path

题意:

给出一个\(n \cdot n\)的矩阵,再给出两个长度为\(n\)的序列\(b, c\),并且有\(a_{i, j} = b_i + c_j\),定义一条'Even Path'为一条经过的格子上面都是偶数的路径。

现在每次询问给出\(x_1, y_1, x_2, y_2\),询问\((x_1, y_1) \rightarrow (x_2, y_2)\)是否存在一条'Even Path'

思路:

发现路径的扩展每次都是扩展一行或者一列,那么当且仅当\(b[x_1] \cdots b[x_2]\)这一段数的奇偶性相同并且\(c[x_1] \cdots c[x_2]\)这一段数的奇偶性相同即可。

代码:

view code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, q, a[N], b[N], idA[N], idB[N]; int main() {
while (scanf("%d%d", &n, &q) != EOF) {
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
a[i] %= 2;
}
for (int i = 1; i <= n; ++i) {
scanf("%d", b + i);
b[i] %= 2;
}
idA[1] = 1;
idB[1] = 1;
for (int i = 2; i <= n; ++i) {
if (a[i] == a[i - 1]) {
idA[i] = idA[i - 1];
} else {
idA[i] = idA[i - 1] + 1;
}
if (b[i] == b[i - 1]) {
idB[i] = idB[i - 1];
} else {
idB[i] = idB[i - 1] + 1;
}
// cout << idA[i] << " " << idB[i] << endl;
}
int x[2], y[2];
while (q--) {
scanf("%d%d%d%d", x, y, x + 1, y + 1);
if (idA[x[0]] == idA[x[1]] && idB[y[0]] == idB[y[1]]) {
puts("YES");
} else {
puts("NO");
}
}
}
return 0;
}

E. Songwriter

题意:

给出一个序列\(a_i\),要求构造一个序列\(b_i\),满足\(b_i \in [L, R]\),并且\(b_i\)和\(b_{i + 1}\)的大小关系和\(a_i\)与\(a_{i + 1}\)相同

并且满足对于任意\(i \in [1, n - 1]\),都有\(|b_i - b_{i + 1}| \leq K\)。

输出满足要求的字典序最小的\(b_i\)

思路:

令\(l_n = L, r_n = R\),然后往前推出每个\(b_i\)的合法取值范围。

然后从前往后贪心即可。

代码:

view code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, L, R, K, a[N], l[N], r[N]; void gao() {
l[n] = L, r[n] = R;
for (int i = n - 1; i >= 1; --i) {
if (a[i] == a[i + 1]) {
l[i] = l[i + 1];
r[i] = r[i + 1];
} else if (a[i] < a[i + 1]) {
r[i] = r[i + 1] - 1;
l[i] = max(L, l[i + 1] - K);
} else if (a[i] > a[i + 1]) {
l[i] = l[i + 1] + 1;
r[i] = min(R, r[i + 1] + K);
}
if (l[i] > r[i]) {
puts("-1");
return;
}
}
int x = l[1];
for (int i = 1; i <= n; ++i) {
printf("%d%c", x, " \n"[i == n]);
if (i < n) {
if (a[i] < a[i + 1]) {
x = max(l[i + 1], x + 1);
} else if (a[i] > a[i + 1]) {
x = max(x - K, l[i + 1]);
}
}
}
} int main() {
while (scanf("%d%d%d%d", &n, &L, &R, &K) != EOF) {
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
}
gao();
}
return 0;
}

G. Performance Review

代码:

view code
#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;
const int INF = 0x3f3f3f3f; int n, m, q;
vector<vector<int> >G;
int a[N], rk[N], remind[N]; struct SEG {
struct node {
int Min;
int lazy; node() {} node(int _Min, int _lazy) {
Min = _Min;
lazy = _lazy;
} void up(int x) {
Min += x;
lazy += x;
}
}t[N << 2]; void down(int id) {
int &lazy = t[id].lazy;
if (lazy) {
t[id << 1].up(lazy);
t[id << 1 | 1].up(lazy);
lazy = 0;
}
} void pushup(int id) {
t[id].Min = min(t[id << 1].Min, t[id << 1 |1].Min);
} void build(int id, int l, int r) {
t[id] = {0, 0};
if (l == r) {
t[id].Min = remind[l];
t[id].lazy = 0;
return ;
}
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
pushup(id);
} void modify(int id, int l, int r, int ql, int qr, int v) {
if (ql > qr) return ;
if (l >= ql && r <= qr) {
t[id].up(v);
return ;
}
int mid = (l + r) >> 1;
down(id);
if (ql <= mid) modify(id << 1, l, mid, ql, qr, v);
if (qr > mid) modify(id << 1 | 1, mid + 1, r, ql, qr, v);
pushup(id);
} int query(int id, int l, int r, int ql, int qr) {
if (l >= ql && r <= qr) return t[id].Min;
int mid = (l + r);
down(id);
int res = INF;
if (ql <= mid) res = min(res, query(id << 1, l, mid, ql, qr));
if (qr > mid) res = min(res, query(id << 1 | 1, mid + 1, r, ql, qr));
return res;
}
}seg; int main() {
while (scanf("%d %d %d", &n, &m, &q) != EOF) {
G.clear();
G.resize(m + 1);
rk[1] = 1;
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
if (a[i] > a[1]) {
rk[1]++;
}
}
for (int i = 1, r, b; i <= m; ++i) {
scanf("%d", &r);
rk[i + 1] = rk[i];
for (int j = 1; j <= r; ++j) {
scanf("%d", &b);
G[i].push_back(b);
if (b > a[1]) {
rk[i + 1]++;
}
}
remind[i] = n - r - rk[i];
}
seg.build(1, 1, m);
for (int _q = 1, x, y, z; _q <= q; ++_q) {
scanf("%d %d %d", &x, &y, &z);
int pre = G[x][y - 1], now = z;
if (pre < a[1] && now > a[1]) {
seg.modify(1, 1, m, x + 1, m, -1);
}
if (pre > a[1] && now < a[1]) {
seg.modify(1, 1, m, x + 1, m, 1);
}
int rank = seg.t[1].Min;
puts(rank < 0 ? "0" : "1");
G[x][y - 1] = z;
}
}
return 0;
}

H. Twin Buildings

题意:

给出\(n\)个地基,要造两个占地面积相同(长宽相同)的房子,问最大占地面积是多少。

可以建在两个地基上,也可以建在一个地基上

思路:

  • 建在一个地基上:暴力枚举
  • 建在两个地基上:容易发现,肯定有其中一个地基的一边被完整用上了,那么枚举这一边,然后在从所有最长边大于等于这个变成的地基中按另一边排序选最大和次大来建,这个用堆维护即可

代码:

view code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 10;
int n, ce;
struct E {
ll x, y; int id;
bool operator < (const E &other) const {
return x < other.x;
}
}e[N]; int main() {
while (scanf("%d", &n) != EOF) {
ce = 0;
for (int i = 1, x, y; i <= n; ++i) {
scanf("%d%d", &x, &y);
e[++ce] = {x, y, i};
e[++ce] = {y, x, i};
}
sort(e + 1, e + 1 + ce);
priority_queue <E> pq;
ll res = 0;
for (int i = ce; i >= 1; --i) {
res = max(res, e[i].x * e[i].y);
ll now = e[i].x;
pq.push({e[i].y, e[i].x, e[i].id});
while (pq.size() > 1) {
E t1 = pq.top(); pq.pop();
E t2 = pq.top(); pq.pop();
if (t1.id == t2.id) {
pq.push(t1);
} else {
pq.push(t1);
pq.push(t2);
break;
}
}
if (pq.size() > 1) {
E t1 = pq.top(); pq.pop();
E t2 = pq.top(); pq.pop();
res = max(res, now * t2.x * 2);
pq.push(t1);
pq.push(t2);
}
}
printf("%lld", res / 2);
puts((res % 2) ? ".5" : ".0");
}
return 0;
}

J. Tiling Terrace

题意:

给出一个字符串,里面只包含'.', '#':

  • 如果拼成'.',那么会得到\(G_1\)的分数
  • 如果拼成'..',那么会得到\(G_2\)的分数
  • 如果拼成'.#.',那么会得到\(G_3\)的分数

现在要将该字符串分成若干段,每一段都是上述的某一个,使得分数最大,并且保证字符串中'#'的个数不超过\(50\)。

但是分段后,要满足第一种类型字符串不超过\(K\)个

思路:

考虑'..'可以换成两个'.',所以\(f[i][j]\)表示前\(i\)个字符,有\(j\)个第三种类型字符串的情况下,最多包含多少个第二类型字符串,然后枚举每种状态贪心即可。

代码:

view code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 10;
int n, limit, pre[N], g[3], f[N][60];
char s[N]; ll get(ll x, ll y) {
if (x >= limit || g[0] * 2 <= g[1]) {
x = min(x, 1ll * limit);
return x * g[0] + y * g[1];
}
if (limit - x >= y * 2) {
x += y * 2;
return x * g[0];
}
if ((limit - x) % 2 == 0) {
int need = limit - x;
y -= need / 2;
x += need;
return x * g[0] + y * g[1];
} else {
int need = limit - x - 1;
y -= need / 2;
x += need;
--y;
return x * g[0] + y * g[1] + max(g[0], g[1]);
}
} int main() {
while (scanf("%d%d", &n, &limit) != EOF) {
memset(f, 0, sizeof f);
for (int i = 0; i < 3; ++i) scanf("%d", g + i);
scanf("%s", s + 1);
memset(f, -0x3f, sizeof f);
f[0][0] = 0;
pre[0] = 0;
for (int i = 1; i <= n; ++i) {
pre[i] = pre[i - 1] + (s[i] == '.');
for (int j = 0; j <= 50; ++j) {
f[i][j] = f[i - 1][j];
}
if (i > 1 && s[i] == '.' && s[i - 1] == '.') {
for (int j = 0; j <= 50; ++j) {
f[i][j] = max(f[i][j], f[i - 2][j] + 1);
}
}
if (i > 2 && s[i] == '.' && s[i - 1] == '#' && s[i - 2] == '.') {
for (int j = 0; j <= 50; ++j) {
f[i][j + 1] = max(f[i][j + 1], f[i - 3][j]);
}
}
}
ll res = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= 50 && f[i][j] >= 0; ++j) {
ll now = 1ll * j * g[2];
ll x = pre[i] - (j + f[i][j]) * 2;
ll y = f[i][j];
now += get(x, y);
res = max(res, now);
}
}
printf("%lld\n", res);
}
return 0;
}

K. Addition Robot

线段树维护矩阵乘法。

代码:

view code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, mod = 1e9 + 7;
int n, q; char s[N];
struct Matrix {
int a[2][2];
void init() { a[0][0] = a[1][1] = 1; a[0][1] = a[1][0] = 0; }
int* operator[] (int x) { return a[x]; }
Matrix operator * (Matrix b) {
Matrix res;
res[0][0] = (1ll * a[0][0] * b[0][0] % mod + 1ll * a[0][1] * b[1][0] % mod) % mod;
res[0][1] = (1ll * a[0][0] * b[0][1] % mod + 1ll * a[0][1] * b[1][1] % mod) % mod;
res[1][0] = (1ll * a[1][0] * b[0][0] % mod + 1ll * a[1][1] * b[1][0] % mod) % mod;
res[1][1] = (1ll * a[1][0] * b[0][1] % mod + 1ll * a[1][1] * b[1][1] % mod) % mod;
return res;
}
}A, B, res; struct SEG {
struct node {
Matrix a[2];
int lazy;
void init() {
a[0].init(); a[1].init();
lazy = 0;
}
void up() {
swap(a[0], a[1]);
lazy ^= 1;
}
}t[N << 2];
void pushup(int id) {
t[id].a[0] = t[id << 1 | 1].a[0] * t[id << 1].a[0];
t[id].a[1] = t[id << 1 | 1].a[1] * t[id << 1].a[1];
}
void down(int id) {
int &lazy = t[id].lazy;
if (lazy) {
t[id << 1].up();
t[id << 1 | 1].up();
lazy = 0;
}
}
void build(int id, int l, int r) {
if (l == r) {
t[id].a[0] = A;
t[id].a[1] = B;
if (s[l] == 'B') {
swap(t[id].a[0], t[id].a[1]);
}
return;
}
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
pushup(id);
}
void modify(int id, int l, int r, int ql, int qr) {
if (l >= ql && r <= qr) {
t[id].up();
return;
}
int mid = (l + r) >> 1;
down(id);
if (ql <= mid) modify(id << 1, l, mid, ql, qr);
if (qr > mid) modify(id << 1 | 1, mid + 1, r, ql, qr);
pushup(id);
}
Matrix query(int id, int l, int r, int ql, int qr) {
if (l >= ql && r <= qr) return t[id].a[0];
int mid = (l + r) >> 1;
down(id);
Matrix res; res.init();
if (qr > mid) res = res * query(id << 1 | 1, mid + 1, r, ql, qr);
if (ql <= mid) res = res * query(id << 1, l, mid, ql, qr);
return res;
}
}seg; int main() {
A = {1, 1, 0, 1};
B = {1, 0, 1, 1};
while (scanf("%d%d", &n, &q) != EOF) {
scanf("%s", s + 1);
seg.build(1, 1, n);
int op, l, r, a, b;
for (int i = 1; i <= q; ++i) {
scanf("%d%d%d", &op, &l, &r);
if (op == 1) {
seg.modify(1, 1, n, l, r);
} else {
scanf("%d%d", &a, &b);
res = {a, 0, b, 0};
res = seg.query(1, 1, n, l, r) * res;
printf("%d %d\n", res[0][0], res[1][0]);
}
}
}
return 0;
}

2019-2020 ICPC, Asia Jakarta Regional Contest的更多相关文章

  1. 2019-2020 ICPC, Asia Jakarta Regional Contest (Online Mirror, ICPC Rules, Teams Preferred)

    2019-2020 ICPC, Asia Jakarta Regional Contest (Online Mirror, ICPC Rules, Teams Preferred) easy: ACE ...

  2. 2019-2020 ICPC, Asia Jakarta Regional Contest H. Twin Buildings

    As you might already know, space has always been a problem in ICPC Jakarta. To cope with this, ICPC ...

  3. 2018 ICPC Asia Jakarta Regional Contest

    题目传送门 题号 A B C D E F G H I J K L 状态 Ο . . Ο . . Ø Ø Ø Ø . Ο Ο:当场 Ø:已补 .  :  待补 A. Edit Distance Thin ...

  4. 2019-2020 ICPC, Asia Jakarta Regional Contest C. Even Path

    Pathfinding is a task of finding a route between two points. It often appears in many problems. For ...

  5. 2019-2020 ICPC, Asia Jakarta Regional Contest A. Copying Homework

    Danang and Darto are classmates. They are given homework to create a permutation of N integers from  ...

  6. 模拟赛小结:2019-2020 ICPC, Asia Jakarta Regional Contest

    比赛链接:传送门 离金最近的一次?,lh大佬carry场. Problem A. Copying Homework 00:17(+) Solved by Dancepted 签到,读题有点慢了.而且配 ...

  7. 2019-2020 ICPC, Asia Jakarta Regional Contest C. Even Path(思维)

    Pathfinding is a task of finding a route between two points. It often appears in many problems. For ...

  8. 2019-2020 ICPC, Asia Jakarta Regional Contest A. Copying Homework (思维)

    Danang and Darto are classmates. They are given homework to create a permutation of N integers from  ...

  9. Asia Jakarta Regional Contest 2019 I - Mission Possible

    cf的地址 因为校强, "咕咕十段"队获得了EC-final的参赛资格 因为我弱, "咕咕十段"队现在银面很大 于是咕咕十段决定进行训练. 周末vp了一场, 这 ...

随机推荐

  1. ps 指令

    ps显示系统当前进程信息, ps 存在多个版本,因此 ps options 的种类繁多.这里只列举平时开发过程中常用的命令,如果有错误或者更好的例子.烦请在评论区指出 语法 ps [options] ...

  2. GitHub的Fork是什么意思

    GitHub的Fork 是什么意思[转] GitHub Help Simple guide to forks in GitHub and Git GitHub的Fork 是什么意思-N神3-博客园 G ...

  3. 【SoloPi】SoloPi使用1-初次使用,环境准备(Windows版)

    下载配置Android SDK路径前往 https://developer.android.com/studio/releases/platform-tools#downloads 下载对应系统版本的 ...

  4. ABP 基于DDD的.NET开发框架 学习(四)时间控件采用datetimepicker注意事项

    $('#datetimepicker1').datetimepicker({ format: 'yyyy/mm/dd hh:ii:ss',//这是只能用小写的大写的与ABP中的字母识别起冲突 loca ...

  5. SQL链接服务器查询-OPENQUERY的使用

    OpenQuery: 用途:与其他Server交互的技术,通过它能够直接访问其他数据库资源.可以跨平台连接,包括Oracle   --创建链接服务器 exec sp_addlinkedserver ' ...

  6. 转 C# GDI+ 实现橡皮筋技术

    http://www.cnblogs.com/arxive/p/6080085.html 应该有很多人都在寻找这方面的资料,看看下面我做的,或许对你会有所帮助,但愿如此. 为了实现橡皮筋技术,我用了两 ...

  7. Python基础初识

    一.安装 暂时没空写,预留 二.python基础初识 2.1 注释 当行注释:# 被注释内容 多行注释:'''被注释内容''',或者"""被注释内容"" ...

  8. PyCharm 占用过大 C 盘空间,system 配置文件迁移

    随着 PyCharm 的持续使用,对应 C:\Users\<username>\.PyCharm<2018.3> 下的文件大小会持续增大,且通常为 system 文件夹下的内容 ...

  9. 【转载】C#使用Split函数根据特定分隔符分割字符串

    在C#程序开发过程中,很多时候可能需要将字符串根据特定的分割字符分割成字符或者List集合,例如根据逗号将字符串分割为数组,或者根据竖线将字符串分割成数组,C#中提供了Split()函数来快速将字符串 ...

  10. mysql各版本驱动

    http://central.maven.org/maven2/mysql/mysql-connector-java/5.1.9/