AtCoder Beginner Contest 224 复盘

在回家的车上打的,效果挺差。

A

一遍 AC。

std::string ss;

int main() {
    cin >> ss;
    int n = (int) ss.size();
    if (ss[n - 1] == 'r' && ss[n - 2] == 'e') cout << "er" << endl;
    else cout << "ist" << endl;
    return 0;
}

B

一遍 AC。

const int MAXN = 50 + 10;

int n, m, aa[MAXN][MAXN];

int main() {
    n = read(); m = read();
    rep (i, 1, n) rep (j, 1, m) aa[i][j] = read();

    bool flag = true;
    rep (i1, 1, n) rep (i2, i1 + 1, n) rep (j1, 1, m) rep (j2, j1 + 1, m) {
        if (aa[i1][j1] + aa[i2][j2] <= aa[i1][j2] + aa[i2][j1]);
        else flag = false;
    }
    if (flag) puts("Yes");
    else puts("No");
    return 0;
}

C. Triangle?

虽然是神必题,但是我被卡精度了,第二个样例答案一直差 2,换了题解的写法才过

const int MAXN = 300 + 10;

struct Point {
    int x, y;
} ps[MAXN];

int n;

int main() {
    n = read();
    rep (i, 1, n) {
        ps[i].x = readll(); ps[i].y = readll();
    }
    long long int ans = 0;
    rep (i, 1, n) {
        rep (j, i + 1, n) {
            rep (k, j + 1, n) {
                int x1 = ps[i].x, x2 = ps[j].x, x3 = ps[k].x;
                int y1 = ps[i].y, y2 = ps[j].y, y3 = ps[k].y;
                ans += (std::abs((x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)) > 0);
            }
        }
    } printf("%lld\n", ans);
    return 0;
}

D

挺基础的图论模型题,但是调了好久才过,原因是肌肉记忆写了个 typo

#错误警示:不要相信肌肉记忆。

const int MAXN = 9 + 2;
const int MAXS = 362880 + 10;

int m;
std::vector<int> G[MAXN];
int pow10[10];

struct Node {
    int u, w;
    bool operator < (const Node &th) const {
        return w > th.w;
    }
};

std::map<int, int> dist;
std::map<int, bool> vis;

void sp(int u) {
    std::priority_queue<Node> q;
    q.push({u, dist[u] = 0});
    while (!q.empty()) {
        int now = q.top().u; q.pop();
        if (vis[now]) continue;
        vis[now] = true;
//        DEBUG(now);
        for (int p = 0; p < 9; ++p) {
            int nxt = now;
            if ((now / pow10[p]) % 10 == 0) continue;
//            DEBUG(p);
            forall (G[p + 1], i) {
                int v = G[p + 1][i];
                if ((nxt / pow10[v - 1]) % 10 == 0) {
                    int mov = (now / pow10[p]) % 10;
                    nxt -= pow10[p] * mov;
                    nxt += mov * pow10[v - 1];
                    if (!dist.count(nxt)) dist[nxt] = 0x3f3f3f3f;
                    if (dist[nxt] > dist[now] + 1) {
//                        if (nxt == 87654321) DEBUG(now);
//                    DEBUG(v);
                        q.push({nxt, dist[nxt] = dist[now] + 1});
                    }
                }
            }
        }
    }
}

int main() {
    m = read();
    pow10[0] = 1;
    rep (i, 1, 9) pow10[i] = pow10[i - 1] * 10;
    rep (i, 1, m) {
        int u = read(); int v = read();
        G[u].push_back(v); G[v].push_back(u);
    }
    int pre_stat = 0;
    for (int i = 1; i <= 8; ++i) {
        int x = read();
        pre_stat += pow10[x - 1] * i;
    }
//    DEBUG(pre_stat);
    sp(pre_stat);
    int finstat = 87654321;
    if (!dist.count(finstat)) puts("-1");
    else printf("%d\n", dist[finstat]);
    return 0;
}

然后我过掉 D 题电脑就没电了。考试到此终结。

E. Integers on Grid

可以发现最终形成的图是一张 DAG,所以一个显然的做法是建图跑最长路。

但其实你甚至不用建图(因为建图挺麻烦的,需要搞个双指针),直接记搜就可以了,在 dfs 里面确定接下来要走的那个点。

而且你甚至不用记搜,换一下 DP 顺序,value 从高到低 DP,用类似前缀和优化的方法记一下每一行每一列 DP 的最大值,然后就可以常数时间转移了。

因为你需要排序,所以时间复杂度 \(O(n\log n)\) 级别的。可以用 std::map 实现。

const int MAXN = 2e5 + 10;

int h, w, n;

std::map<int, std::vector<int> > mp;

int rr[MAXN], cc[MAXN], aa[MAXN];

int dp[MAXN], rmax[MAXN], cmax[MAXN];

int main() {
    h = read(); w = read(); n = read();
    rep (i, 1, n) {
        rr[i] = read(); cc[i] = read(); aa[i] = read();
        mp[aa[i]].push_back(i);
    }
    for (auto it = mp.rbegin(); it != mp.rend(); it++) {
        for (auto u : it->second) dp[u] = std::max(rmax[rr[u]], cmax[cc[u]]);
        for (auto u : it->second) {
            rmax[rr[u]] = std::max(rmax[rr[u]], dp[u] + 1);
            cmax[cc[u]] = std::max(cmax[cc[u]], dp[u] + 1);
        }
    }
    rep (i, 1, n) printf("%d\n", dp[i]);
    return 0;
}

下面这个是记搜的做法,只 WA 了一个点,至今没调出来。

const int MAXN = 2e5 + 10;

int h, w, n;

struct E {
    int id, w;
    bool operator < (const E &th) const {
        return w < th.w;
    }
}; std::set<E> rows[MAXN], cols[MAXN];

int rowi[MAXN], coli[MAXN], vali[MAXN];

int dp[MAXN];
bool vis[MAXN];

int search(int u) {
    if (vis[u]) return dp[u];
    vis[u] = true;
    int &ans = dp[u] = 0;
    {
        int r = rowi[u];
        auto it = rows[r].find({u, vali[u]});
        assert(it != rows[r].end());
        ++it;
        while (it != rows[r].end() && it->w == vali[u]) ++it;
        if (it != rows[r].end()) ans = std::max(ans, search(it->id) + 1);
    }
    {
        int r = coli[u];
        auto it = cols[r].find({u, vali[u]});
        assert(it != cols[r].end());
        ++it;
        while (it != cols[r].end() && it->w == vali[u]) ++it;
        if (it != cols[r].end()) ans = std::max(ans, search(it->id) + 1);
    }
    return ans;
}

int main() {
    h = read(); w = read(); n = read();
    rep (i, 1, n) {
        rowi[i] = read(); coli[i] = read(); vali[i] = read();
        rows[rowi[i]].insert({i, vali[i]});
        cols[coli[i]].insert({i, vali[i]});
    }
    rep (i, 1, n) printf("%d\n", search(i));
    return 0;
}
posted @ 2021-10-25 11:14  Handwer  阅读(83)  评论(0编辑  收藏  举报