Codeforces Round #375 (Div. 2) ABCDEF题解
来源:互联网 发布:2017年7月进出口数据 编辑:程序博客网 时间:2024/05/17 04:15
A. The New Year: Meeting Friends
同一直线上的三个人要集合,求三个人一共走的距离的最小值。
max(a, b, c) - min(a, b, c)
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define mp make_pair#define pb push_back#define FIN freopen("in.txt", "r", stdin)#define FOUT freopen("out.txt", "w", stdout)#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define lowbit(x) ((x)&(-(x)))#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)#define debug puts("-------------");//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double eps = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 5e4 + 50;const int MAXM = 1e4 + 50;int a, b, c;int main() {#ifdef LOCAL_NORTH// FIN;#endif // LOCAL_NORTH while (~scanf("%d%d%d", &a, &b, &c)) { printf("%d\n", max(a, max(b, c)) - min(a, min(b, c))); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
B. Text Document Analysis
输出括号外的单词的最大长度已经括号内单词的个数。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cctype>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define mp make_pair#define pb push_back#define FIN freopen("in.txt", "r", stdin)#define FOUT freopen("out.txt", "w", stdout)#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define lowbit(x) ((x)&(-(x)))#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)#define debug puts("-------------");//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double eps = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 5e4 + 50;const int MAXM = 1e4 + 50;int n;string s;int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (cin >> n >> s) { int ans1 = 0, ans2 = 0, len = 0, in = 0; for (int i = 0; i < n; i++) { if (isalpha(s[i])) len++; else { if (!in) ans1 = max(ans1, len); else if (len) ans2++; len = 0; if (s[i] == '(' || s[i] == ')') in = 1 - in; } } ans1 = max(ans1, len); printf("%d %d\n", ans1, ans2); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
C. Polycarp at the Radio
有n首曲子明天要演奏,一个人希望他喜欢的m个乐队演奏的歌曲数的最大值最小。输出改变次数最少的演奏安排。
目的是使m个乐队至少演奏n/m首。
统计一下原来这m个乐队演奏的数目并排序。目的是使原本歌曲数多的演奏n/m+1首或n/m首(根据原本的次数判断一下改变后按演奏多少),原本少的演奏n/m首。这样一来,改变的次数就必定最小。
计算出为符合要求,乐队i需要增加或减少的歌曲数op[i]。这时op数组有正有负,来一次n^2的操作把所有的负数消掉,即找到op[i] < 0,op[j] > 0,然后op[i]++,op[j]--。
最后遍历整个序列,把大于m的乐队变为小于等于m的乐队。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cctype>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define mp make_pair#define pb push_back#define FIN freopen("in.txt", "r", stdin)#define FOUT freopen("out.txt", "w", stdout)#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define lowbit(x) ((x)&(-(x)))#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)#define debug puts("-------------");//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double eps = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 2e3 + 50;const int MAXM = 1e4 + 50;int m, n, a[MAXN], op[MAXN], c[MAXN];struct node{ int c, id; node(int _c, int _id) {c = _c; id = _id;} bool operator < (const node& _) const {return c > _.c;}};int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%d%d", &n, &m)) { memset(c, 0, sizeof(c)); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); if (a[i] >= 1 && a[i] <= m) c[a[i]]++; } vector<node> v; for (int i = 1; i <= m; i++) v.pb(node(c[i], i)); sort(v.begin(), v.end()); int ans1 = n / m, ans2 = 0;// for (int i = 0; i < m; i++) printf("[%d]%c", v[i].c, " \n"[i == m - 1]); int fck = n % m; for (int i = 0; i < m; i++) { int id = v[i].id; op[id] = n / m - c[id]; while (fck && op[id] <= -1) { op[id]++; fck--; } ans2 += abs(op[id]); }// for (int i = 1; i <= m; i++) printf("%d%c", op[i], " \n"[i == m]); for (int i = 1; i <= m; i++) { while (op[i] < 0) { int s = -1; for (int j = 1; j <= m; j++) { if (op[j] > 0) { s = j; break; } } for (int j = 1; j <= n; j++) { if (a[j] == i) { a[j] = s; op[i]++; op[s]--; ans2--; break; } } } } printf("%d %d\n", ans1, ans2); for (int i = 1; i <= n; i++) { if (a[i] < 1 || a[i] > m) { for (int j = 1; j <= m; j++) { if (op[j] > 0) { op[j]--; a[i] = j; break; } } } printf("%d%c", a[i], " \n"[i == n]); } }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
D. Lakes in Berland
把最少的水地变为土地,使得湖(连通块)的数目等于k。
bfs一遍统计出湖的个数、每个湖的大小以及湖的任意一点。
排序后,从每个湖中的点开始,把前tot-k个湖变为土地。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cctype>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define mp make_pair#define pb push_back#define FIN freopen("in.txt", "r", stdin)#define FOUT freopen("out.txt", "w", stdout)#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define lowbit(x) ((x)&(-(x)))#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)#define debug puts("-------------");//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double eps = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 100 + 50;const int MAXM = 1e4 + 50;int n, m, k, d[4][2] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};char p[MAXN][MAXN];bool vis[MAXN][MAXN];struct node{ int x, y, c; bool operator < (const node& _) const {return c < _.c;}}lakes[MAXN * MAXN];int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%d%d%d", &n, &m, &k)) { memset(vis, false, sizeof(vis)); for (int i = 1; i <= n; i++) scanf("%s", p[i] + 1); int tot = 0; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (p[i][j] == '.' && !vis[i][j]) { bool ok = true; int cnt = 0; queue<PII > q; q.push(mp(i, j)); vis[i][j] = true; while (!q.empty()) { PII cur = q.front(); q.pop(); int x = cur.first, y = cur.second; cnt++; if (x < 1 || x > n || y < 1 || y > m) { ok = false; continue; } for (int l = 0; l < 4; l++) { int xx = x + d[l][0], yy = y + d[l][1]; if (xx >= 0 && xx <= n + 1 && yy >= 0 && yy <= m + 1 && !vis[xx][yy] && p[xx][yy] != '*') q.push(mp(xx, yy)); vis[xx][yy] = true; } } if (ok) { lakes[tot].c = cnt; lakes[tot].x = i; lakes[tot++].y = j; } } } } sort(lakes, lakes + tot); int ans = 0; for (int i = 0; i < tot - k; i++) { ans += lakes[i].c; queue<PII > q; q.push(mp(lakes[i].x, lakes[i].y)); p[lakes[i].x][lakes[i].y] = '*'; while (!q.empty()) { PII cur = q.front(); q.pop(); int x = cur.first, y = cur.second; for (int j = 0; j < 4; j++) { int xx = x + d[j][0], yy = y + d[j][1]; if (xx > 0 && xx <= n && yy > 0 && yy <= m && p[xx][yy] != '*') { p[xx][yy] = '*'; q.push(mp(xx, yy)); } } } } printf("%d\n", ans); for (int i = 1; i <= n; i++) printf("%s\n", p[i] + 1); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
E. One-Way Reform
把无向图转化为有向图,同时使得出度等于入度的点最多。并打印边。
为了使出度等于入度的点最多,要把原图转化为欧拉图,操作为:原图中奇数度的点一定有偶数个,所有将度为奇数的点两两(不是点i与所有的奇数度点连边,而是点i与任意一奇数度点相连)之间加一条边。
然后用Fleury打印欧拉回路即可,注意添加的边不要打印。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cctype>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define mp make_pair#define pb push_back#define FIN freopen("in.txt", "r", stdin)#define FOUT freopen("out.txt", "w", stdout)#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define lowbit(x) ((x)&(-(x)))#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)#define debug puts("-------------");//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double eps = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 1e5 + 50;const int MAXM = 1e5 + 50;int n, m, d[MAXN];bool vis[MAXN];struct Edge{ int v, f, p, nxt;} E[MAXM << 1];int tot, Head[MAXN];void edge_init() { tot = 0; memset(Head, -1, sizeof(Head));}void edge_add(int u, int v, int p) { E[tot].v = v; E[tot].f = 0; E[tot].p = p; E[tot].nxt = Head[u]; Head[u] = tot++; E[tot].v = u; E[tot].f = 0; E[tot].p = p; E[tot].nxt = Head[v]; Head[v] = tot++;}vector<int> odd;void dfs(int u) { vis[u] = true; for (int i = Head[u]; ~i; i = E[i].nxt) { if (E[i | 1].f) continue; E[i | 1].f = 1; if (E[i].p) printf("%d %d\n", u, E[i].v); dfs(E[i].v);// return; !!!! }}int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH int T; scanf("%d", &T); while (T--) { memset(d, 0, sizeof(d)); memset(vis, false, sizeof(vis)); odd.clear(); edge_init(); scanf("%d%d", &n, &m); for (int i = 0; i < m; i++) { int u, v; scanf("%d%d", &u, &v); edge_add(u, v, 1); d[u]++; d[v]++; } int ans = 0; for (int i = 1; i <= n; i++) if (d[i] & 1) odd.pb(i); else ans++; for (int i = 0, sz = odd.size(); i < sz - 1; i += 2) edge_add(odd[i], odd[i + 1], 0); printf("%d\n", ans); for (int i = 1; i <= n; i++) if (!vis[i]) dfs(i); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
F. st-Spanning Tree
在原图的基础上构建一棵生成树,同时s的度不大于ds,t的度不大于dt,并打印边。
为了使和s、t相连的边数最少,需要在去掉s和t的每个连通分量内构建一棵生成树。
然后把所有生成树连到s和t上。需要注意不是随便连,否则会出现一个连通分量既可以连到s,也可以连到t,但最后连错导致s和t度数错误。一种可行的方法是每次遇到上文描述的情况,将生成树连到距离度数限制较大的点上。
经过上一步,原图已经变成了两棵生成树,同时注意到图中没有被选中用来构建生成树的边只有3种:
1)端点为s和t;2)一端为s,另一端不为t;3)一端为t,另一端不为s。
现在只需要在一棵生成树上找到任意一条连上后符合题意的边。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cctype>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define mp make_pair#define pb push_back#define FIN freopen("in.txt", "r", stdin)#define FOUT freopen("out.txt", "w", stdout)#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define lowbit(x) ((x)&(-(x)))#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)#define debug puts("-------------");//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double eps = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 2e5 + 50;const int MAXM = 4e5 + 50;int n, m, s, t, ds, dt;struct Edge{ int u, v;}E[MAXM];int par[MAXN];int Find(int x) {return par[x] == x ? x : par[x] = Find(par[x]);}void unite(int a, int b) { int x = Find(a), y = Find(b); if (x != y) par[x] = y;}vector<PII > ans;bool link[MAXN][2];int STlink[MAXN], dus, dut;bool ST2S[MAXN], ST2T[MAXN];void solveST() { for (int i = 0; i < m; i++) { int u = E[i].u, v = E[i].v; if (u == s || u == t || v == s || v == t) continue; if (Find(u) != Find(v)) { unite(u, v); ans.pb(mp(u, v)); } } memset(ST2S, false, sizeof(ST2S)); memset(ST2T, false, sizeof(ST2T)); for (int i = 1; i <= n; i++) { if (i == s || i == t) continue; if (link[i][0]) ST2S[Find(i)] = true; if (link[i][1]) ST2T[Find(i)] = true; }}void linkST() { dus = dut = 0; memset(STlink, -1, sizeof(STlink)); for (int i = 1; i <= n; i++) { if (i == s || i == t) continue; int stNo = Find(i); if (STlink[stNo] != -1) continue; bool ok1 = (ST2S[stNo] && dus < ds && link[i][0]); bool ok2 = (ST2T[stNo] && dut < dt && link[i][1]); int tmp = -1; if (ok1 && ok2) { if (ds - dus > dt - dut) tmp = s; else tmp = t; } else if (ok1) tmp = s; else if (ok2) tmp = t; if (tmp == s) { STlink[stNo] = 0; unite(i, s); ans.pb(mp(i, s)); dus++; } else if (tmp == t) { STlink[stNo] = 1; unite(i, t); ans.pb(mp(i, t)); dut++; } }}bool Link() { if (dus < ds && dut < dt && link[t][0]) { dut++, dus++; ans.pb(mp(s, t)); unite(s, t); return true; } for (int i = 1; i <= n; i++) { if (i == s || i == t) continue; if (Find(i) == Find(s)) { if (dut < dt && link[i][1]) { dut++; ans.pb(mp(t, i)); unite(i, t); return true; } } else if (Find(i) == Find(t)) { if (dus < ds && link[i][0]) { dus++; ans.pb(mp(s, i)); unite(i, s); return true; } } } return false;}int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%d%d", &n, &m)) { ans.clear(); memset(link, false, sizeof(link)); //link[i][0]表示是i否与s相连,link[i][1]表示i是否与t相连。 for (int i = 1; i <= n; i++) par[i] = i; for (int i = 0; i < m; i++) scanf("%d%d", &E[i].u, &E[i].v); scanf("%d%d%d%d", &s, &t, &ds, &dt); for (int i = 0; i < m; i++) { if (E[i].u == s || E[i].v == s) link[E[i].u + E[i].v - s][0] = true; if (E[i].u == t || E[i].v == t) link[E[i].u + E[i].v - t][1] = true; } link[s][0] = link[t][1] = true; solveST(); //构建生成树 linkST(); //生成树连向s和t if (dus > ds || dut > dt) { printf("No\n"); continue; } bool ok = Link(); //两棵生成树相连 for (int i = 1; i <= n; i++) ok &= (Find(i) == Find(1)); if (!ok) { printf("No\n"); continue; } if (dus <= ds && dut <= dt) { printf("Yes\n"); int sz = ans.size(); for (int i = 0; i < sz; i++) printf("%d %d\n", ans[i].first, ans[i].second); } else printf("No\n"); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
- Codeforces Round #375 (Div. 2) ABCDEF题解
- Codeforces Round #377 (Div. 2) ABCDEF 题解
- Codeforces Round #436 (Div. 2) ABCDEF
- Codeforces Round #424 Div. 2 【ABCDEF】[补完]
- Codeforces Round #375 (Div. 2)题解
- Codeforces Round #375 (Div. 2)题解报告
- Codeforces Round #375 (Div. 2) 个人题解
- Codeforces Round #375 (Div. 2) 题解
- 【codeforces】Codeforces Round #276 (Div. 2) 题解
- 【codeforces】Codeforces Round #277 (Div. 2) 题解
- 【codeforces】Codeforces Round #279 (Div. 2) 题解
- 【codeforces】Codeforces Round #283 (Div. 2) 【题解】
- 【codeforces】Codeforces Round #291 (Div. 2) 题解
- Codeforces Round #131 (Div. 2) 完整题解
- Codeforces Round #135 (Div. 2)题解
- Codeforces Round #192 (Div. 2) 题解报告
- Codeforces Round #194 (Div. 2) 题解
- Codeforces Round #216 (Div. 2)部分题解
- Linux下的文件目录管理
- DVBlast
- 如何求解问题-现代启发式方法(第8-9章)
- 欧拉工程第16题 2的1000次方的各位之和是多少?
- 对于无法进行MvcMovies的解决方法
- Codeforces Round #375 (Div. 2) ABCDEF题解
- Enable 360-wifi2 on BeagleBone Black
- 解读 RtlGetSystem
- Java中构造方法打印九九乘法表
- 0808:局部代码块、构造代码块、静态代码块、多线程代码块
- HDU ACM 11 2057 A + B Again
- Linux中带缓存的文件复制
- POJ_3320
- XFS文件系统简介(xfs_info观察相关数据)