Codeforces Round #374 (Div. 2) ABCDE题解

来源:互联网 发布:网络用语缩写 编辑:程序博客网 时间:2024/05/17 13:45

A. One-dimensional Japanese Crossword

输出连续的B序列的个数及长度。

统计一下就可以了。

#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 long long 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 ERR = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 1e3 + 50;const int MAXM = 1e4 + 50;int n, m, ans[105];char s[105];int main() {#ifdef LOCAL_NORTH    FIN;#endif // LOCAL_NORTH    while (~scanf("%d%s", &n, s)) {        m = 0;        int cnt = 0;        for (int i = 0; s[i]; i++) {            if (s[i] == 'W') {                if (cnt) {                    ans[m++] = cnt;                    cnt = 0;                }            } else cnt++;        }        if (cnt) ans[m++] = cnt;        printf("%d\n", m);        for (int i = 0; i < m; i++) printf("%d%c", ans[i], " \n"[i == m - 1]);    }#ifdef LOCAL_NORTH    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH    return 0;}

B. Passwords

给出若干个字符串,其中一个是密码。然后按照长度从小到大输入字符串,长度相同则可以按任意顺序输入,每1秒输入一次,连错k次则等5秒。求输入密码所需要的最小及最大时间。

统计出

1.长度小于psw的字符串个数,求出最短时间。

2.长度小于psw的字符串个数+长度等于psw长度且字典序小于psw的字符串个数,求出最大时间。

#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 long long 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 ERR = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 1e3 + 50;const int MAXM = 1e4 + 50;int n, k;string cor, s[105];int main() {#ifdef LOCAL_NORTH    FIN;#endif // LOCAL_NORTH    while (cin >> n >> k) {        for (int i = 0; i < n; i++) cin >> s[i];        cin >> cor;        int cnt1 = 0, cnt2 = 0;        for (int i = 0; i < n; i++) {            if (s[i].size() < cor.size()) cnt1++;            if (s[i].size() < cor.size() || (s[i].size() == cor.size() && s[i] != cor)) cnt2++;        }        int ans1 = cnt1 / k * 5 + cnt1;        int ans2 = cnt2 / k * 5 + cnt2;        cout << ans1 + 1 << " " << ans2 + 1 << endl;    }#ifdef LOCAL_NORTH    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH    return 0;}

C. Journey

n个点,m条边的DAG,走每条边都需要一定的时间,求在规定时间内从1到n,且途中经过最多的点数,然后打印路径。

这道题我的是O(n^3)的方法,O((n+m)n)的方法可以去看一下其他菊苣的博客。

首先拓扑排序一下,然后按照拓扑序dp,状态转移方程是

if (ans[u][j] + E[l].w <= t)    ans[v][j + 1] = min(ans[v][j + 1], ans[u][j] + E[l].w);

其中,E[l]是连接u,v的边,E[l].w为边权。

ans全部初始化为INF,dp之后判断ans[n][i]是否为INF就能知道能否在规定时间内到达n。

然后就是打印路径,从n开始逆向dfs。

#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 ERR = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 5e3 + 50;const int MAXM = 1e4 + 50;int n, m, t;LL ans[MAXN][MAXN];int c, ttmp[MAXN];bool flag;struct {    int u, v, w, nxt;}E[MAXN];int tot, Head[MAXN];int in[MAXN], tp[MAXN];void init() {    tot = 0;    memset(Head, -1, sizeof(Head));    memset(in, 0, sizeof(in));    memset(ans, 0x3f, sizeof(ans));}void edge_add(int u, int v, int w) {    E[tot].u = u;    E[tot].v = v;    E[tot].w = w;    E[tot].nxt = Head[u];    Head[u] = tot++;}void tpsort() {    int sz = 0;    queue<int> q;    for (int i = 1; i <= n; i++) {        if (!in[i]) {            q.push(i);            tp[++sz] = i;        }    }    while (!q.empty()) {        int u = q.front();        q.pop();        for (int i = Head[u], v; ~i; i = E[i].nxt) {            v = E[i].v;            in[v]--;            if (!in[v]) {                q.push(v);                tp[++sz] = v;            }        }    }}void dfs(int cnt, int pos, int ran) {    if (flag) return;    if (cnt == 1 && pos == 1 && ran == 0) {        flag = true;        for (int i = 1; i <= c; i++) printf("%d%c", ttmp[i], " \n"[i == c]);        return;    }    for (int i = 0; i < m; i++) {        int u = E[i].u, v = E[i].v, w = E[i].w;        if (v == pos && ans[v][cnt] - ans[u][cnt - 1] == w) {            ttmp[cnt] = pos;            dfs(cnt - 1, u, ran - w);        }    }}int main() {#ifdef LOCAL_NORTH    FIN;#endif // LOCAL_NORTH    while (~scanf("%d%d%d", &n, &m, &t)) {        init();        for (int i = 0, u, v, w; i < m; i++) {            scanf("%d%d%d", &u, &v, &w);            edge_add(u, v, w);            in[v]++;        }        tpsort();        ans[1][1] = 0;        for (int i = 1, u, v; i <= n; i++) {            u = tp[i];            for (int j = 1; j <= i; j++) {                if (ans[u][j] == INFLL) continue;                for (int l = Head[u]; ~l; l = E[l].nxt) {                    v = E[l].v;                    if (ans[u][j] + E[l].w <= t)                        ans[v][j + 1] = min(ans[v][j + 1], ans[u][j] + E[l].w);                }            }        }        LL tmp = INFLL;        for (int i = n; i >= 1; i--) {            if (ans[n][i] != INFLL) {                c = i;                tmp = ans[n][i];                break;            }        }        printf("%d\n", c);        flag = false;        ttmp[1] = 1;        dfs(c, n, tmp);    }#ifdef LOCAL_NORTH    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH    return 0;}

D. Maxim and Array

给出一个序列,要求进行至多k次+x或-x的操作,使得所有元素乘积最小,n、k均为2e5。

首先要知道,在一个正数序列的某一项+x,使得乘积最大,那么这个x需要加在最小的数上。

1)初始序列中有奇数个负数

在不改变符号的情况下,使得所有元素绝对值最大。实现就是把所有数放入优先队列中,每次取最小值,+x,入队。

2)初始序列中有偶数个负数

a)绝对值最大的元素 <= k * t

首先将绝对值最小的符号变号,然后进行与1)相同的操作

b)绝对值最小的元素 > k * t

将绝对值最小的元素 - k * t

#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 = 2e5 + 50;const int MAXM = 1e4 + 50;int n, k, sgn[MAXN];LL x, num[MAXN];struct node{    int id;    LL val;    node(int _id, LL _val) {id = _id; val = _val;}    bool operator < (const node& _) const {return val > _.val;}};void dec() {    priority_queue<node> q;    for (int i = 0; i < n; i++) q.push(node(i, num[i]));    int cnt = k;    while (cnt--) {        node t = q.top();        int id = t.id;        q.pop();        t.val += x;        q.push(t);        num[id] = t.val;    }}int main() {#ifdef LOCAL_NORTH    FIN;#endif // LOCAL_NORTH    while (~scanf("%d%d%I64d", &n, &k, &x)) {        LL min_abs = INFLL;        int neg = 0, min_index;        for (int i = 0; i < n; i++) {            scanf("%I64d", &num[i]);            if (num[i]) sgn[i] = num[i] / abs(num[i]);            else sgn[i] = 1;            if (num[i] < 0) neg++;            if (abs(num[i]) < abs(min_abs)) {                min_index = i;                min_abs = num[i];            }            num[i] = abs(num[i]);        }        if (neg & 1) {            dec();        } else {            if (abs(min_abs) < k * x) {                sgn[min_index] *= -1;                num[min_index] = (abs(min_abs) / x + 1) * x - abs(min_abs);                k -= abs(min_abs) / x + 1;                dec();            } else if (abs(min_abs) > k * x) {                num[min_index] -= k * x;            } else num[min_index] = 0;        }        for (int i = 0; i < n; i++) printf("%I64d%c", sgn[i] * num[i], " \n"[i == n - 1]);    }#ifdef LOCAL_NORTH    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH    return 0;}

E. Road to Home

n个区间,人只能在区间内唱歌,每次消耗p时间,一旦停下,需要 t 时间的间隔才能继续唱。求最多能唱多少首歌。

dp。

A[i]表示在区间i的走到右端点时,最多能唱多少首歌。

B[i]表示在唱完A[i]首歌,最靠近0的位置。

输入i个区间的同时,每次找到最靠近 l[i] 的B的下标的前一项c,然后从c到i-1,更新A和B,统计最大的A即可。

#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 = 4e5 + 50;int L, n, p, t;int A[MAXN], B[MAXN];void upd(int i, int a, int b) {    if (a > A[i]) {        A[i] = a;        B[i] = b;    } else if (a == A[i] && b < B[i]) {        B[i] = b;    }}int main() {#ifdef LOCAL_NORTH    FIN;#endif // LOCAL_NORTH    while (~scanf("%d%d%d%d", &L, &n, &p, &t)) {        memset(A, 0, sizeof(A));        memset(B, 0, sizeof(B));        A[0] = 0;        B[0] = -t;        int l, r, c = 0, ans = 0;        for (int i = 1; i <= n; i++) {            scanf("%d%d", &l, &r);            while (c < i - 1 && B[c] + t < l) c++;            if (c) c--;            upd(i, A[i - 1], B[i - 1]);            for (int j = c; j < i; j++) {                if (B[j] + p <= r) {                    int left = max(l, B[j] + t);                    int cnt = (r - left) / p;                    int pos = left + cnt * p;                    upd(i, A[j] + cnt, pos);                } else break;            }            ans = max(ans, A[i]);        }        printf("%d\n", ans);    }#ifdef LOCAL_NORTH    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH    return 0;}


0 0