Codeforces Round #374 Div. 2 review

Link

A. One-dimensional Japanese Crossword

Just count consecutive ‘B’ in the sequence.

/*
 *
 */
#include <cstdio>
#include <iostream>

using namespace std;

int a[100];
char c[100];

int main(){
#ifndef ONLINE_JUDGE
    freopen("a5.in", "r", stdin);
#endif
    int n;
    scanf("%d", &n);
    scanf("%s", c);

    int k = 0;
    int count = 0;
    for (int i = 0; i < n; ++i) {
        if (c[i] == 'B') {
            count++;
        } else {
            if (count != 0) {
                a[k++] = count;
                count = 0;
            }
        }
    }
    if (count != 0) a[k++] = count;

    printf("%d\n", k);
    for (int j = 0; j < k; ++j) {
        printf("%d%c", a[j], j==k-1 ? '\n' : ' ');
    }

    return 0;
}

B. Passwords

This is also easy, just count the number for each string length. You even don’t need to process any string manipulation.

/*
 *
 */
#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;

char pass[105][105];
char correct[105]; //correct pass
int count[105]; // count[i] means how many pass is length i.

int main(){
#ifndef ONLINE_JUDGE
    freopen("b2.in", "r", stdin);
#endif
    int n, k;
    scanf("%d %d", &n, &k);
    for (int i = 0; i < n; ++i) {
        scanf("%s", pass[i]);
        int len = strlen(pass[i]);
        count[len]++;
    }
    scanf("%s", correct);
    int correct_len = strlen(correct);
    int wrongpass = 0;
    for (int j = 0; j < correct_len; ++j) {
        wrongpass += count[j];
    }
    int min = wrongpass + wrongpass / k * 5 + 1;
    wrongpass += count[correct_len] - 1;
    int max = wrongpass + wrongpass / k * 5 + 1;
    printf("%d %d", min, max);

    return 0;
}

C. Journey

I felt it is difficult than problem D. During the contest, I tried to solve it by DFS but I got TLE.

/*
 * TLE
 * DFS method is not fast enough
 */
#include <cstdio>
#include <iostream>
#include <vector>

using namespace std;

// road[i][j] is edge from i to start[i][j].first.
// start[i][j].second is the cost for this edge.
vector<pair<int, int> > road[5005];
int optimumroad[5005];

int n, m, T;
int maximumVisit = 0;
// current city with current time
bool dfs(int city, int time, int visited) {
    if (time > T) return false;
    if (city == n) {
        if (visited > maximumVisit) {
            maximumVisit = visited;
            return true;
        } else {
            return false;
        }
    }
    bool maximumRouteFound = false;
    for (int i = 0; i < road[city].size(); ++i) {
        if (dfs(road[city][i].first, time + road[city][i].second, visited + 1)) {
            optimumroad[city] = road[city][i].first;
            //cout << city << " " << road[city][i].first << endl;
            maximumRouteFound = true;
        }

    }
    return maximumRouteFound;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("c4.in", "r", stdin);
#endif
    scanf("%d %d %d", &n, &m, &T);

    for (int i = 0; i < m; ++i) {
        int u, v, t;
        scanf("%d %d %d", &u, &v, &t);
        road[u].push_back(make_pair(v, t));
    }

    dfs(1, 0, 1);
    printf("%d\n", maximumVisit);
    int currentcity = 1;
    printf("1 ");
    while (true) {
        currentcity = optimumroad[currentcity];
        if (currentcity == n) {
            printf("%d\n", n);
            break;
        } else {
            printf("%d ", currentcity);
        }
    }
    return 0;
}

To get answer, we can use DP (dynamic programming) to reduce computational complexity as \(O(mn)\).

/*
 * DP method
 * Accepted	93 ms	98300 KB
 */
#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

#define INF (1e9+5)

struct edge {
    int from;
    int to;
    int cost;
};

vector<edge> roadvec;
int optimumroad[5005];

int n, m, T;
int maximumVisit = 0;


// dp[i][j]: Minimum cost when already visited i cities, for city j.
// INF indicates not reachable.
// Do not use 0 for i and j.
int dp[2][5005];

// to remember optimal path. path[i][j]: To visit i cities at city j, optimal path is come from path[i][j].
int path[5005][5005];

int main(){
#ifndef ONLINE_JUDGE
    freopen("c4.in", "r", stdin);
#endif
    scanf("%d %d %d", &n, &m, &T);

    for (int i = 0; i < m; ++i) {
        int u, v, t;
        scanf("%d %d %d", &u, &v, &t);
        roadvec.push_back(edge{u, v, t});
    }


    for (int j = 0; j < 5005; ++j) {
        dp[0][j] = INF;
    }
    dp[0][1] = 0;

    for (int i = 1; i < n; ++i) {
        for (int j = 0; j < 5005; ++j) {
            dp[1][j] = INF;  // Need to init each time!
        }
        for (int j = 0; j < m; ++j) {
            if (dp[0][roadvec[j].from] + roadvec[j].cost < dp[1][roadvec[j].to]) {
                dp[1][roadvec[j].to] = dp[0][roadvec[j].from] + roadvec[j].cost;
                path[i+1][roadvec[j].to] = roadvec[j].from;
                //cout << "i " << i << ", from " << roadvec[j].from <<
                //        ", to " << roadvec[j].to << ", cost " << roadvec[j].cost <<
                //        ", dp[1][to] " << dp[1][roadvec[j].to] << endl;
            }
        }
        if (dp[1][n] <= T) {
            maximumVisit = i+1;
        }
        swap(dp[0], dp[1]);
    }
    // Reconstruct optimum road path
    optimumroad[maximumVisit] = n;
    for (int i = maximumVisit - 1; i > 0; --i) {
        optimumroad[i] = path[i+1][optimumroad[i+1]];
    }

    printf("%d\n", maximumVisit);
    for (int k = 1; k <= maximumVisit; ++k) {
        printf("%d%c", optimumroad[k], k==maximumVisit ? '\n' : ' ');
    }
    return 0;
}

D. Maxim and Array

Basic strategy to get minimum product is as follows,

1. If the product is positive, then we want to reduce it. We can change the sign of number whose absolute value is minimum.

2. If the product is 0, then there exists at least one 0 in the array. We can change this 0 to get total product as negative.

3. If the product is negative, then we want to keep the sign of product as negative and just want to get the total absolute value product as maximum. To do this, we should get minimum absolute value and change this absolute value by +x.

To get minimum absolute value for each iteration efficiently, we can use priority_queue.

/*
 * Accepted	233 ms	9300 KB
 * use priority_queue
 */
#include <cstdio>
#include <iostream>
#include <queue>


using namespace std;

typedef long long ll;
typedef pair<ll, ll> P;

ll sign[200005]; // sign: +1 positive or 0, -1 negative.
ll ans[200005];

ll checksign(ll a) {
    if (a >= 0) {
        return 1;
    } else {
        return -1;
    }
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("d5.in", "r", stdin);
#endif
    ll n, k, x;
    scanf("%lli %lli %lli", &n, &k, &x);

    priority_queue<P, vector<P>, greater<P> > q;
    ll negative_count = 0;
    ll a;
    for (int i = 0; i < n; ++i) {
        scanf("%lli", &a);
        sign[i] = checksign(a);
        if (sign[i] == -1) negative_count++;
        q.push(make_pair(a * sign[i], i));
    }

    P current = q.top();
    ll min = current.first;
    if (negative_count % 2 == 0 && min >= k * x) { // positive case: no 0 exists and we cannot make total product as 0 or negative
        q.pop();
        q.push(make_pair(current.first - k * x, current.second));
    } else {
        if (negative_count % 2  == 0) {  // Make negative_count as odd
            ll repeat = min / x + 1;
            q.pop();
            q.push(make_pair(-(current.first - repeat * x), current.second));
            k -= repeat;
            if (sign[current.second] == 1) {
                sign[current.second] = -1;
                negative_count++;
            } else {
                sign[current.second] = 1;
                negative_count--;
            }
        }
        while (k > 0) {
            current = q.top(); q.pop();
            q.push(make_pair(current.first + x, current.second));
            k--;
        }
    }

    while (!q.empty()) {
        P current = q.top(); q.pop();
        ans[current.second] = sign[current.second] * current.first;
    }

    for (int i = 0; i < n; ++i) {
        printf("%lli%c", ans[i], i==n-1 ? '\n' : ' ');
    }
    return 0;
}

Leave a Comment

Your email address will not be published. Required fields are marked *