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;}


0 0
原创粉丝点击