Contest Info


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

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

Solutions


A. Berstagram

题意:

给出\(n\)个数,刚开始第\(i\)个数在第\(i\)个位置,有\(m\)次操作,将标号为\(a_i\)的数和它前面那个数交换位置,如果它已经在最前面了,那么不操作。

最后输出\(n\)行,表示每个数所待过的位置的下标的最小值和最大值

思路:

每次交换只会影响两个数,暴力即可。

代码:

view code

```c++
#include
using namespace std;
using pII = pair;
#define fi first
#define se second
const int N = 4e5 + 10;
int n, m, a[N], fa[N], b[N];
pII res[N];
void up(int x, int y) {
res[x].fi = min(res[x].fi, y);
res[x].se = max(res[x].se, y);
}

int main() {

while (scanf("%d%d", &n, &m) != EOF) {

for (int i = 1; i <= n; ++i) a[i] = i, fa[i] = i, res[i] = pII(i, i);

for (int i = 1; i <= m; ++i) scanf("%d", b + i);

for (int i = 1; i <= m; ++i) {

int x = b[i];

if (fa[x] == 1) continue;

int pre = a[fa[x] - 1];

swap(fa[x], fa[pre]);

swap(a[fa[x]], a[fa[pre]]);

up(x, fa[x]);

up(pre, fa[pre]);

// for (int j = 1; j <= n; ++j)

// printf("%d%c", a[j], " \n"[j == n]);

}

for (int i = 1; i <= n; ++i)

printf("%d %d\n", res[i].fi, res[i].se);

}

return 0;

}

</details>

### B. The Feast and the Bus

题意:
有$n$个人,$k$个小组,每个人属于一个小组,每个小组至少有一个人。
现在要租$r$辆巴士,每辆巴士的容量都为$s$,但是$s$和$r$可以自己定,使得能够装下所有人,并且满足以下两个限制条件:
- 同一组的人在同一辆巴士
- 一辆巴士最多有两个小组的人 使得$r \cdot s$最小 思路:
考虑$k$很小,我们可以枚举$r$,然后可以算出有多少辆巴士必须要两个小组,然后贪心放,让小组人数多的占用单组巴士,小组人数少的贪心配对,即最大的配最小的,次大的配次小的$\cdots$
时间复杂度$O(k^2)$ 代码:
<details>
<summary>view code</summary> ```c++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 5e5 + 10;
int n, k, a[N];
ll gao(int x) {
ll s = 0;
int need = k - (2 * x - k);
for (int i = 1, j = need; i < j; ++i, --j) {
s = max(s, 1ll * a[i] + a[j]);
}
for (int i = need + 1; i <= k; ++i)
s = max(s, 1ll * a[i]);
return s;
} int main() {
while (scanf("%d%d", &n, &k) != EOF) {
memset(a, 0, sizeof a);
for (int i = 1, x; i <= n; ++i) {
scanf("%d", &x);
++a[x];
}
sort(a + 1, a + 1 + k);
ll res = 1e18;
for (int i = (k + 1) / 2; i <= k; ++i) {
res = min(res, 1ll * i * gao(i));
}
printf("%lld\n", res);
}
return 0;
}

C. Trip to Saint Petersburg

题意:

给出\(n\)个工作,和一个参数\(k\)。

每个工作的工作时间为\([l_i, r_i]\),可以获得\(p_i\)的利润,并且工作随便选,工作时间可以重叠。

唯一的代价就是所选择的工作中的最小的\(L = l_i\),最大的\(R = r_i\),代价就是\(k \cdot (R - L + 1)\)。

问所能获得的最大利润。

思路:

枚举右端点\(R\),然后线段树维护左端点的贡献,每次要将\(r_i = R\)的工作的贡献加给左端点在\([1, l_i]\)范围内的。

然后查询区间最值即可。

代码:

view code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pIL = pair<int, ll>;
#define fi first
#define se second
const int N = 2e5 + 10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int n, m, pl[N], pr[N]; ll k;
vector <vector<pIL>> vec; struct SEG {
struct node {
ll Max, lazy; int pos;
node() { Max = -INF; lazy = pos = 0; }
void up(ll x) {
Max += x;
lazy += x;
}
node operator + (const node &other) const {
node res = node();
if (Max >= other.Max) {
res.Max = Max;
res.pos = pos;
} else {
res.Max = other.Max;
res.pos = other.pos;
}
return res;
}
}t[N << 2], res;
void build(int id, int l, int r) {
t[id] = node();
if (l == r) {
t[id].Max = 0;
t[id].pos = l;
return;
}
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
t[id] = t[id << 1] + t[id << 1 | 1];
}
void down(int id) {
ll &lazy = t[id].lazy;
if (lazy) {
t[id << 1].up(lazy);
t[id << 1 | 1].up(lazy);
lazy = 0;
}
}
void update(int id, int l, int r, int ql, int qr, ll v) {
if (l >= ql && r <= qr) {
t[id].up(v);
return;
}
int mid = (l + r) >> 1;
down(id);
if (ql <= mid) update(id << 1, l, mid, ql, qr, v);
if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, v);
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;
down(id);
if (ql <= mid) query(id << 1, l, mid, ql, qr);
if (qr > mid) query(id << 1 | 1, mid + 1, r, ql, qr);
}
}seg; int main() {
while (scanf("%d%lld", &n, &k) != EOF) {
vec.clear(); vec.resize(N);
m = 2e5;
for (int i = 1; i <= n; ++i) {
int l, r; ll p;
scanf("%d%d%lld", &l, &r, &p);
pl[i] = l, pr[i] = r;
vec[r].push_back(pIL(l, p));
}
ll p = 0; int L = -1, R = -1;
seg.build(1, 1, m);
for (int i = 1; i <= m; ++i) {
seg.update(1, 1, m, 1, i, -k);
for (auto &it : vec[i])
seg.update(1, 1, m, 1, it.fi, it.se);
seg.res = SEG::node();
seg.query(1, 1, m, 1, i);
if (seg.res.Max > p) {
p = seg.res.Max;
L = seg.res.pos;
R = i;
}
}
if (p == 0) puts("0");
else {
vector <int> vec;
for (int i = 1; i <= n; ++i)
if (pl[i] >= L && pr[i] <= R)
vec.push_back(i);
int sze = vec.size();
printf("%lld %d %d %d\n", p, L, R, sze);
for (int i = 0; i < sze; ++i)
printf("%d%c", vec[i], " \n"[i == sze - 1]);
}
}
return 0;
}

E. The Coronation

题意:

给出\(n\)个\(01\)串,每个\(01\)串可以\(reverse\),求最少的\(reverse\)次数,使得任意两个串的有大于等于\(k\)个位置的字符是相同的。

代码:

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

using namespace std;

const int N = 60;

struct Edge {
int v, p;//1 same Edge() {} Edge(int v, int p): v(v), p(p) {}
}; bool F;
int n, m, k;
string s[N];
vector<vector<Edge> > G; bool ok(const string &S, const string &T) {
int cnt = 0;
for (int i = 0; i < m; ++i) {
if (S[i] == T[i]) ++cnt;
}
return cnt >= k;
} int col[N], vis[N];
vector<int> vec, res; void DFS(int u) {
if (!F) return ;
vis[u] = 1;
vec.push_back(u);
for (auto &it: G[u]) {
if (col[it.v] == -1) {
if (it.p) {
col[it.v] = col[u];
} else {
col[it.v] = col[u] ^ 1;
}
DFS(it.v);
} else {
if (it.p) {
if (col[it.v] != col[u]) {
F = false;
break;
}
} else {
if (col[it.v] != (col[u] ^ 1)) {
F = false;
break;
}
}
}
}
} int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
cin >> n >> m >> k;
G.clear();
G.resize(n + 1);
memset(vis, 0, sizeof vis);
memset(col, -1, sizeof col);
for (int i = 1; i <= n; ++i) {
cin >> s[i];
}
F = true;
for (int i = 1; i <= n; ++i) {
for (int j = i + 1; j <= n; ++j) {
int cnt = 0;
int same = 0;
if (ok(s[i], s[j])) {
cnt++;
same = 1;
}
reverse(s[j].begin(), s[j].end());
cnt += ok(s[i], s[j]);
reverse(s[j].begin(), s[j].end());
if (cnt == 0) {
F = false;
break;
}
if (cnt == 1) {
G[i].push_back(Edge(j, same));
G[j].push_back(Edge(i, same));
}
}
if (!F) {
F = false;
break;
}
}
if (!F) {
cout << "-1\n";
continue;
}
res.clear();
for (int i = 1; i <= n; ++i) {
if (!vis[i]) {
col[i] = 1;
vec.clear();
DFS(i);
int cnt[2] = {0, 0};
for (auto &it: vec) {
cnt[col[it]]++;
}
int now = 0;
if (cnt[1] < cnt[0]) {
now = 1;
}
for (auto &it : vec) {
if (col[it] == now) {
res.push_back(it);
}
}
}
}
if (!F) {
cout << "-1\n";
} else {
int sze = res.size();
cout << sze << "\n";
for (int i = 0; i < sze; ++i) {
if (i) cout << " ";
cout << res[i];
}
cout << "\n";
}
}
return 0;
}

F. Data Center

题意:

给出一个矩形的面积\(n\),求所有合法矩形中的最小周长。

思路:

暴力分解。

代码:

view code
#include <bits/stdc++.h>
using namespace std; int main() {
int n;
while (scanf("%d", &n) != EOF) {
int res = 1e9;
for (int i = 1; i <= n; ++i) {
if (n % i == 0) {
res = min(res, i + n / i);
}
}
res *= 2;
printf("%d\n", res);
}
return 0;
}

G. Discarding Game

题意:

有两个人玩游戏,刚开始两个人的分数都是\(0\),每一轮,\(A\)的分数会加上\(a_i\),\(B\)的分数会加上\(b_i\),如果某个人的分数大于等于\(k\),它就输了,如果两个人都大于等于\(k\),两个人都输了。

如果最后过完了\(n\)轮,两人的分数都小于\(k\),那么是平局。

赢的情况是其中某个人输了,那么另一个人就赢了。

现在\(A\)有超能力,它可以在每一轮加分结束后按下一个按钮,假定此时\(A\)的分数为\(x\),\(B\)的分数为\(y\), \(A\)的分数变成\(max(0, x - y)\),\(B\)的分数变成\(max(0, y - x)\)。

现在求最少次数使得\(A\)赢了。

H. Happy Birthday

题意:

给出\([0, 9]\)每种数字的个数,问最小的不能被拼出来的数是多少。

代码:

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

using namespace std;

int a[100];

int main() {
int T;
scanf("%d", &T);
while (T--) {
for (int i = 0; i < 10; ++i) scanf("%d", a + i);
int Min = a[0] + 2;
for (int i = 1; i < 10; ++i) Min = min(Min, a[i] + 1);
if (Min == a[0] + 2) {
printf("1");
for (int i = 1; i <= a[0] + 1; ++i) printf("0");
puts("");
} else {
for (int i = 1; i < 10; ++i) {
if (Min == a[i] + 1) {
for (int j = 1; j <= a[i] + 1; ++j) printf("%d", i);
puts("");
break;
}
}
}
}
return 0;
}

J. The Parade

代码:

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

using namespace std;

typedef long long ll;

const int N = 1e5 + 10;

int n;
ll k;
ll a[N], b[N]; bool check(ll x) {
ll cnt = 0, remind = 0;
for (int i = 1; i <= n; ++i) {
b[i] = a[i];
if (b[i] >= x - remind) {
cnt++;
b[i] -= x - remind;
remind = 0;
}
cnt += b[i] / x;
remind = b[i] % x;
if (cnt >= k) return true;
}
return cnt >= k;
} int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d %lld", &n, &k);
for (int i = 1; i <= n; ++i) {
scanf("%lld", a + i);
}
ll l = 1, r = 1e17, res = 0;
while (r - l >= 0) {
ll mid = (l + r) >> 1;
if (check(mid)) {
res = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
printf("%lld\n", res * k);
}
return 0;
}

L. Divide The Students

题意:

有三类人,每类人有\(a, b, c\)个。

现在要将这三类人分成三组,使得第一类和第三类人不能在同一组,并且使得所有组的最大人数最少。

思路:

令\(a > c\),那么将\(c\)单独放在一组,将\(a\)均分成两组,然后\(b\)每次选一个人数最少的组放。

代码:

view code
#include <bits/stdc++.h>
using namespace std; int main() {
int _T; scanf("%d", &_T);
while (_T--) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
// int res = max((a + b + c + 2) / 3, min(a, c));
// printf("%d\n", res);
if (a < c) swap(a, c);
int A[3] = {a / 2, a - a / 2, c};
while (b) {
sort(A, A + 3);
++A[0];
--b;
}
printf("%d\n", max(A[0], max(A[1], A[2])));
}
return 0;
}

M. SmartGarden

题意:

给出一个\(n \cdot n\)的矩形,其中对角线和对角线下面一条线是墙,其他地方是蔬菜,类似这样:



现在每次可以选择若干个行,若干个列,将这些行列相交的地方浇上水,次数最多为\(50\)次,并且不能浇到墙,并且每棵蔬菜都要被浇到。

N. Wires

题意:

给出\(n\)条边,点的标号在\([1, 10^9]\),现在可以修改某条边的某个端点,使得这\(n\)条边所构成的图是一个连通块。

使得修改次数最少。

思路:

显然最少修改次数为连通块个数 - 1。

随便选取一个连通块出来,让其他连通块都连向这个连通块。

然后考虑每个连通块里:

  • 如果有\(1\)度顶点,直接改掉这个\(1\)度顶点
  • 那么没有\(1\)度顶点,那么必然有环,随便改掉环上的一条边即可

代码:

view code
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
struct Hash {
vector <int> a;
void init() { a.clear(); }
void add(int x) { a.push_back(x); }
void gao() { sort(a.begin(), a.end()); a.erase(unique(a.begin(), a.end()), a.end()); }
int get(int x) { return lower_bound(a.begin(), a.end(), x) - a.begin() + 1; }
}hs;
struct E {
int u, v;
E() {}
E(int u, int v) : u(u), v(v) {}
}e[N];
struct node {
int id, u, v;
};
vector <vector<node>> G;
vector <node> res;
int n, m, d[N], fa[N], vis[N], Insta[N], used[N], usede[N], F;
int find(int x) { return fa[x] == 0 ? x : fa[x] = find(fa[x]); }
void merge(int u, int v) {
u = find(u); v = find(v);
if (u != v) fa[u] = v;
}
void dfs(int u) {
used[u] = 1;
Insta[u] = 1;
for (auto &it : G[u]) if (!usede[it.id]) {
usede[it.id] = 1;
int v = it.v;
if (Insta[v]) {
if (!F) {
res.push_back({it.id, hs.a[it.u - 1], hs.a[0]});
F = 1;
return;
}
}
if (used[v] == 0) {
dfs(v);
}
if (F) return;
}
Insta[u] = 0;
} int main() {
int _T; scanf("%d", &_T);
while (_T--) {
scanf("%d", &n);
hs.init();
for (int i = 1, u, v; i <= n; ++i) {
scanf("%d%d", &u, &v);
hs.add(u); hs.add(v);
e[i] = E(u, v);
usede[i] = 0;
}
hs.gao();
m = hs.a.size();
for (int i = 1; i <= m; ++i) {
d[i] = fa[i] = 0;
vis[i] = 0;
Insta[i] = used[i] = 0;
}
G.clear(); G.resize(m + 1);
for (int i = 1; i <= n; ++i) {
e[i].u = hs.get(e[i].u);
e[i].v = hs.get(e[i].v);
++d[e[i].u];
++d[e[i].v];
merge(e[i].u, e[i].v);
int u = e[i].u, v = e[i].v;
G[u].push_back({i, u, v});
G[v].push_back({i, v, u});
}
int rt = 1, frt = find(rt);
vis[frt] = 1;
res.clear();
for (int i = 1; i <= n; ++i) {
int &u = e[i].u, &v = e[i].v;
if (d[u] > d[v]) swap(u, v);
int fu = find(u);
if (vis[fu]) continue;
if (d[u] == 1) {
res.push_back({i, hs.a[u - 1], hs.a[0]});
vis[fu] = 1;
}
}
for (int i = 1; i <= m; ++i) {
int fi = find(i);
if (vis[fi]) continue;
F = 0;
vis[fi] = 1;
dfs(i);
}
int sze = res.size();
printf("%d\n", sze);
for (int i = 0; i < sze; ++i) {
printf("%d %d %d\n", res[i].id, res[i].u, res[i].v);
}
}
return 0;
}

2019-2020 ICPC, NERC, Southern and Volga Russian Regional Contest的更多相关文章

  1. 2019-2020 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror, ICPC Rules, Teams Preferred)【A题 类型好题】

    A. Berstagram Polycarp recently signed up to a new social network Berstagram. He immediately publish ...

  2. 2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror, ICPC Rules) D. Firecrackers (贪心,二分)

    题意:有个长度为\(n\)的监狱,犯人在位置\(a\),cop在位置\(b\),你每次可以向左或者向右移动一个单位,或者选择不动并在原地放一个爆竹\(i\),爆竹\(i\)在\(s[i]\)秒后爆炸, ...

  3. 2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror, ICPC Rules) C. Berpizza (STL)

    题意:酒吧里有两个服务员,每个人每次都只能服务一名客人,服务员2按照客人进酒吧的顺序服务,服务员3按照客人的钱来服务,询问\(q\),\(1\)表示有客人进入酒吧,带着\(m\)块钱,\(2\)表示询 ...

  4. 2017 ACM - ICPC Asia Ho Chi Minh City Regional Contest

    2017 ACM - ICPC Asia Ho Chi Minh City Regional Contest A - Arranging Wine 题目描述:有\(R\)个红箱和\(W\)个白箱,将这 ...

  5. 2018-2019 ICPC, NEERC, Southern Subregional Contest

    目录 2018-2019 ICPC, NEERC, Southern Subregional Contest (Codeforces 1070) A.Find a Number(BFS) C.Clou ...

  6. Codeforces 2018-2019 ICPC, NEERC, Southern Subregional Contest

    2018-2019 ICPC, NEERC, Southern Subregional Contest 闲谈: 被操哥和男神带飞的一场ACM,第一把做了这么多题,荣幸成为7题队,虽然比赛的时候频频出锅 ...

  7. 2020 ICPC Universidad Nacional de Colombia Programming Contest

    2020 ICPC Universidad Nacional de Colombia Programming Contest A. Approach 三分 显然答案可以三分,注意\(eps\)还有两条 ...

  8. ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków

    ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków Problem A: Rubik’s Rect ...

  9. ACM ICPC 2010–2011, Northeastern European Regional Contest St Petersburg – Barnaul – Tashkent – Tbilisi, November 24, 2010

    ACM ICPC 2010–2011, Northeastern European Regional Contest St Petersburg – Barnaul – Tashkent – Tbil ...

随机推荐

  1. vmware vcsa-故障1

    1.重启vcsa后不能登陆webclient 做实验得时候重启vcsa后不能登陆 web client 开启vcsa直接进入命令模式,命令行登陆后提示:failed to connect  to se ...

  2. 使用其他身份运行计算机(DOS命令)

    runas/user:administrator cmd d: cd esop sfispri.ini

  3. RabbitMQ 应用一

    (百度百科)MQ全称为Message Queue,消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们.消息传递指的 ...

  4. volatile和锁

    让编译器不要将变量缓存到寄存器,而是每次去访问主板上的内存 可见性 对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入 原子性 对任意单个volatile变量的 ...

  5. MySQL常见问题集锦及注意事项

    一.表设计上的坑 1.字段设计 1.1 字段类型设计 尽量使用整型表示字符串: `INET_ATON(str)`,address to number `INET_NTOA(number)`,numbe ...

  6. MySQL索引机制详解(B+树)

    一.索引是什么? 索引是为了加速对表中数据行的检索而创建的一种分散存储的数据结构. 二.为什么要使用索引? 索引能极大的减少存储引擎需要扫描的数据量. 索引可以把随机IO变成顺序IO. 索引可以帮助我 ...

  7. [LeetCode] 234. 回文链表 ☆(翻转链表)

    描述 请判断一个链表是否为回文链表. 示例 1: 输入: 1->2输出: false示例 2: 输入: 1->2->2->1输出: true 进阶:你能否用 O(n) 时间复杂 ...

  8. Robo 3T SQL

    查询指定日期,指定显示字段,排序,注释功能 db.getCollection('spuBasisInfo') .find({"createTime":{$gte:ISODate(& ...

  9. JAVA 使用原生jdbc批量添加,表被锁住问题

    今天用jdbc批量添加数据的时候遇到了一个问题,当数据添加成功过后,再想对该表进行操作发现表被锁住了,检查了下代码发现事务提交了呀!!!!!!!!!!!! 去网上查了大半天的资料才发现问题,在conn ...

  10. .NET Core 开发常用命令(VS Code)

    在开始开发 .NET Core 项目的时候,有用过 VS2017.VS Code 两个对比下来,VS 虽然开发更便捷但是 VS Code 更适合 .NET Core. 下面就总结一下常用的命令. 一. ...