Codeforces Round #625

A - Journey Planning

题意: 有一列共 n 个城市, 每个城市有美丽值b[i], 要访问一个子序列的城市, 这个子序列相邻项的原项数之差等于美丽值之差, 求最大的美丽值总和.

思路: 对于一个合法的子序列, b[i] - i 结果是一个定值, 统计该值取最大.


view code


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inc(i, l, r) for (int i = l; i <= r; i++)

const int maxn = 1e6 + 5;

int n, b[maxn];

int main() {
    cin >> n;
    map<int, ll> a;
    inc(i, 0, n - 1) {
        cin >> b[i];
        a[b[i] - i] += b[i];
    }
    ll res = 0;
    for (auto ite : a) res = max(res, ite.second);
    cout << res << "\n";
}


B - Navigation System

题意: 给出一个有向图和一个人的行动路径, 这个人每次移动前导航仪会给出从当前点到终点的一条最短路线, 如果这个人移动的路线与之不符, 导航仪会重新生成从下一个点出发到终点的最短路线. 问导航仪生成新路线的最小和最大次数.

思路: bfs求出所有点到终点的最短距离. 如果这个人移动时距离终点不是-1, 那他这次移动一定不在最短路线上; 否则, 检查是否有其他使距离-1的路线, 如果有, 那么就知道导航仪可能会重新生成路线.


view code


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inc(i, l, r) for (int i = l; i <= r; i++)

const int maxn = 1e6 + 5;
const int inf = 0x3f3f3f3f;

vector<int> g[maxn];
vector<int> rg[maxn];
int a[maxn], d[maxn], vis[maxn];
int n, m, u, v, k;

int main() {
    memset(d, 63, sizeof(d));
    cin >> n >> m;
    inc(i, 1, m) {
        cin >> u >> v;
        rg[u].push_back(v);
        g[v].push_back(u);
    }
    cin >> k;
    inc(i, 1, k) cin >> a[i];
    queue<int> que;
    que.push(a[k]);
    d[a[k]] = 0;
    vis[a[k]] = 1;
    while (que.size()) {
        int p = que.front();
        que.pop();
        inc(i, 0, (int)g[p].size() - 1) {
            if (!vis[g[p][i]]) {
                d[g[p][i]] = d[p] + 1;
                que.push(g[p][i]);
                vis[g[p][i]] = 1;
            }
        }
    }
    int res1 = 0, res2 = 0;
    for (int i = 1; i < k; i++) {
        int now = a[i], nxt = a[i + 1];
        if (d[now] != d[nxt] + 1)
            res1++, res2++;
        else
            inc(j, 0, (int)rg[now].size() - 1) {
                if (d[rg[now][j]] + 1 == d[now] && rg[now][j] != nxt) {
                    res2++;
                    break;
                }
            }
    }
    cout << res1 << " " << res2;
}


C - World of Darkraft: Battle for Azathoth

题意: 给出 n 个武器, m 个防具, 分别有攻击力 ai 和防御力 bi, 购买该装备需要的金币ci, 还有 p 个怪兽, 分别具有防御力xi, 攻击力yi, 打败它获得的金币ci. 现要求从中武器和防具中各选出恰好一个, 然后就可以打败 ai > xi 且 bi > yi 低的怪兽. 求最大获利.

思路: 没过, 写一下理论做法, 之后会回来验证. 对所有怪兽排序(不妨以 xi 作为第一关键字), 然后维护关于 yi 的线段树, 表示防御力为 i 时的最大获利, 而攻击力为当前怪兽xi + 1, 这样可以确保扫描过的怪兽 ai > xj, 而 bi > yj只是个区间查询的问题.


view code


NULL


心得: 我这一场就是在玩蛇, 乱交题, 各种bug. 开场A, 假了个枚举每个数作为子序列起点, 再并查集去掉已用的点的做法, 看到TLE的时候脑子才想到正解, 13min累计 2 发过. B题 35min 交的第一发, 但直到 73min 累计交 4 次才过, 中间出现的问题: 从终点出发bfs的图和沿人走的路径的图以为是一个图, 拿 i 当 d[i], 还有统计是否有其它使距离-1的边时没有break重复统计. C题没过, 剩 7min 发现写的是错的, 本来是按每个怪兽为节点查询BIT, 但是最优解并不一定对应打败一个怪兽, 可能是攻击力满足个a怪兽, 防御力却是满足另一个b怪兽. 感觉教训就是, 这场打的有点迷之自信, 想得不全面而不自知.

猜你喜欢

转载自www.cnblogs.com/hs-zlq/p/12391937.html