Codeforces Round 980 div2 个人题解(A~D)

Codeforces Round 980 div2 个人题解(A~D)

Dashboard - Codeforces Round 980 (Div. 2) - Codeforces

火车头

#define _CRT_SECURE_NO_WARNINGS 1

#include <algorithm>
#include <array>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <chrono>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <vector>

#define ft first
#define sd second

#define yes cout << "yes\n"
#define no cout << "no\n"

#define Yes cout << "Yes\n"
#define No cout << "No\n"

#define YES cout << "YES\n"
#define NO cout << "NO\n"

#define pb push_back
#define eb emplace_back

#define all(x) x.begin(), x.end()
#define all1(x) x.begin() + 1, x.end()
#define unq_all(x) x.erase(unique(all(x)), x.end())
#define unq_all1(x) x.erase(unique(all1(x)), x.end())
#define sort_all(x) sort(all(x))
#define sort1_all(x) sort(all1(x))
#define reverse_all(x) reverse(all(x))
#define reverse1_all(x) reverse(all1(x))

#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3fLL

#define RED cout << "\033[91m"
#define GREEN cout << "\033[92m"
#define YELLOW cout << "\033[93m"
#define BLUE cout << "\033[94m"
#define MAGENTA cout << "\033[95m"
#define CYAN cout << "\033[96m"
#define RESET cout << "\033[0m"

// 红色
#define DEBUG1(x)                     \
    RED;                              \
    cout << #x << " : " << x << endl; \
    RESET;

// 绿色
#define DEBUG2(x)                     \
    GREEN;                            \
    cout << #x << " : " << x << endl; \
    RESET;

// 蓝色
#define DEBUG3(x)                     \
    BLUE;                             \
    cout << #x << " : " << x << endl; \
    RESET;

// 品红
#define DEBUG4(x)                     \
    MAGENTA;                          \
    cout << #x << " : " << x << endl; \
    RESET;

// 青色
#define DEBUG5(x)                     \
    CYAN;                             \
    cout << #x << " : " << x << endl; \
    RESET;

// 黄色
#define DEBUG6(x)                     \
    YELLOW;                           \
    cout << #x << " : " << x << endl; \
    RESET;

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// typedef __int128_t i128;

typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;
typedef pair<ll, int> pli;
typedef pair<string, string> pss;
typedef pair<string, int> psi;
typedef pair<string, ll> psl;

typedef tuple<int, int, int> ti3;
typedef tuple<ll, ll, ll> tl3;
typedef tuple<ld, ld, ld> tld3;

typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pli> vpli;
typedef vector<pss> vpss;
typedef vector<ti3> vti3;
typedef vector<tl3> vtl3;
typedef vector<tld3> vtld3;

typedef vector<vi> vvi;
typedef vector<vl> vvl;

typedef queue<int> qi;
typedef queue<ll> ql;
typedef queue<pii> qpii;
typedef queue<pll> qpll;
typedef queue<psi> qpsi;
typedef queue<psl> qpsl;

typedef priority_queue<int> pqi;
typedef priority_queue<ll> pql;
typedef priority_queue<string> pqs;
typedef priority_queue<pii> pqpii;
typedef priority_queue<psi> pqpsi;
typedef priority_queue<pll> pqpll;
typedef priority_queue<psi> pqpsl;

typedef map<int, int> mii;
typedef map<int, bool> mib;
typedef map<ll, ll> mll;
typedef map<ll, bool> mlb;
typedef map<char, int> mci;
typedef map<char, ll> mcl;
typedef map<char, bool> mcb;
typedef map<string, int> msi;
typedef map<string, ll> msl;
typedef map<int, bool> mib;

typedef unordered_map<int, int> umii;
typedef unordered_map<ll, ll> uml;
typedef unordered_map<char, int> umci;
typedef unordered_map<char, ll> umcl;
typedef unordered_map<string, int> umsi;
typedef unordered_map<string, ll> umsl;

std::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());

template <typename T>
inline T read()
{
    T x = 0;
    int y = 1;
    char ch = getchar();
    while (ch > '9' || ch < '0')
    {
        if (ch == '-')
            y = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = (x << 3) + (x << 1) + (ch ^ 48);
        ch = getchar();
    }
    return x * y;
}

template <typename T>
inline void write(T x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x >= 10)
    {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}

/*#####################################BEGIN#####################################*/
void solve()
{
}

int main()
{
    ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    // freopen("test.in", "r", stdin);
    // freopen("test.out", "w", stdout);
    int _ = 1;
    std::cin >> _;
    while (_--)
    {
        solve();
    }
    return 0;
}

/*######################################END######################################*/
// 链接:

A. Profitable Interest Rate

每个测试的时间限制:1秒
每个测试的内存限制:256兆字节

Alice 有 \(a\) 个硬币。她可以开立一个名为“盈利”的银行存款,但开立此存款所需的最低金额为 \(b\) 个硬币。

还有一个名为“无利可图”的存款,可以用任意数量的硬币开立。Alice 注意到,如果她用 \(x\) 个硬币开立“无利可图”存款,则开立“盈利”存款所需的最低金额会减少 \(2x\) 个硬币。但是,这些硬币以后不能存入“盈利”存款。

如果 Alice 首先将一定数量的硬币(可能是 0)存入“无利可图”存款,请帮助她确定她可以存入“盈利”存款的最大硬币数量。如果 Alice 永远无法开立“盈利”存款,则输出 0。

输入

每个测试由多个测试用例组成。第一行包含一个整数 \(t\) \((1 \leq t \leq 10^4)\) — 测试用例的数量。测试用例的描述如下。

每个测试用例的一行包含两个整数 \(a\)\(b\) \((1 \leq a, b \leq 10^9)\) — Alice 拥有的硬币数量以及开立“盈利”存款所需的初始最低金额。

输出

对于每个测试用例,输出一个整数 — Alice 可以存入“盈利”存款的最大硬币数量。如果 Alice 永远无法开立“盈利”存款,则输出 0。

示例

输入

5  
10 5  
7 9  
5 100  
1 1  
1 2  

输出

10  
5  
0  
1  
0  

注意

在第一个测试案例中,\(a \geq b\),因此 Alice 可以立即用所有 10 个硬币开立“盈利”存款。

在第二个测试案例中,Alice 可以用 2 个硬币开立“无盈利”存款。然后她将剩下 5 个硬币,但开立“盈利”存款所需的最低金额将减少 4 个硬币,使其等于 5 个硬币。因此,Alice 将能够用 5 个硬币开立“盈利”存款。

在第三个测试案例中,Alice 将无法开立“盈利”存款。

解题思路

根据题目要求列出公式\(a-x=b-2x\),移项得\(x=b-a\)。再特判一下极端情况即可。

代码实现

void solve()
{
    ll a, b;
    cin >> a >> b;
    if (a >= b)
    {
        cout << a << endl;
        return;
    }
    else if (a * 2 <= b)
    {
        cout << 0 << endl;
        return;
    }
    int d = b - a;
    cout << a - d << endl;
}

B. Buying Lemonade

每个测试的时间限制:1秒

每个测试的内存限制:256兆字节

输入:标准输入

输出:标准输出

有一台出售柠檬水的自动售货机。这台机器共有 \(n\) 个槽位。你知道最初,第 \(i\) 个槽位包含 \(a_i\) 罐柠檬水。机器上还有 \(n\) 个按钮,每个按钮对应一个槽位,每个槽位对应一个按钮。不幸的是,按钮上的标签已经磨损,所以你不知道哪个按钮对应哪个槽位。

当你按下与第 \(i\) 个槽位对应的按钮时,会发生以下两种情况之一:

  1. 如果第 \(i\) 个槽位中有一罐柠檬水,它会掉出来,你会拿走它。此时,第 \(i\) 个槽位中的罐子数量减少了 \(1\)
  2. 如果第 \(i\) 个槽位中没有剩余的柠檬水罐,则不会掉出任何东西。

按下按钮后,罐子会快速掉出,因此无法追踪它从哪个槽位掉落。槽位的内容隐藏在您的视野之外,因此您无法看到每个槽位中剩余的罐子数量。您唯一知道的是槽位中的初始罐子数量: \(a_1, a_2, \ldots, a_n\)

确定需要按下的最少按钮次数,以保证您至少收到 \(k\) 罐柠檬水。

请注意,您可以根据是否收到罐子来调整按钮按下时的策略。保证机器中总共至少有 \(k\) 罐柠檬水。换句话说, \(k \leq a_1 + a_2 + \ldots + a_n\)

输入

每个测试由多个测试用例组成。第一行包含一个整数 \(t\) (\(1 \leq t \leq 10^4\)) — 测试用例的数量。测试用例的描述如下。

每个测试用例的第一行包含两个整数 \(n\)\(k\) (\(1 \leq n \leq 2 \cdot 10^5, 1 \leq k \leq 10^9\)) — 机器中的插槽数量和所需的柠檬水罐数。

每个测试用例的第二行包含 \(n\) 个整数 \(a_1, a_2, \ldots, a_n\) (\(1 \leq a_i \leq 10^9\)) — 插槽中的罐子数量。

保证有 \(k \leq a_1 + a_2 + \ldots + a_n\) ,这意味着机器中至少有 \(k\) 罐柠檬水。

保证所有测试用例的 \(n\) 之和不超过 \(2 \cdot 10^5\)

输出

对于每个测试用例,输出一个整数 — 保证您收到至少 \(k\) 罐柠檬水所需的最少按钮按下次数。

示例

输入

5
2 1
1 1
2 2
1 2
3 4
2 1 3
10 50
1 1 3 8 8 9 12 13 27 27
2 1000000000
1000000000 500000000

输出

1
2
5
53
1000000000

注意

在第一个测试用例中,我们可以简单地按下第一个按钮并收到一罐柠檬水。

在第二个测试用例中,我们可以按下每个按钮一次,确保我们收到 \(2\) 罐柠檬水。请注意,如果我们只是按下一个按钮两次,我们可能不会幸运,那样的话按钮可能对应第一个槽位,在这种情况下我们只会收到 \(1\) 罐柠檬水。

在第三个测试用例中,最优策略之一如下:

  • 按下第一个按钮两次。第一次按下后,肯定会掉出一罐柠檬水。然后有两种选择:
    1. 如果第二次按下后没有掉出柠檬水,我们知道这个按钮一定对应第二个槽位,因为 \(a_2=1\)\(a_1, a_3 > 1\)。然后我们可以按下第二个按钮两次,第三个按钮一次。由于 \(a_1, a_3 \geq 2\),我们肯定会在这三次按下中收到三罐柠檬水。因此,在 \(5\) 次按下后,我们将获得 \(4\) 罐柠檬水。
    2. 如果第二次按下后掉出了一罐柠檬水,我们可以按下第二个按钮一次,第三个按钮一次。在每次按下中,我们肯定会收到一罐柠檬水。因此,在 \(4\) 次按下后,我们将获得 \(4\) 罐柠檬水。

可以证明,仅用 \(4\) 次按下是无法保证收到 \(4\) 罐柠檬水的,因此答案是 \(5\)

解题思路

对于任意一个按钮,如果我们按下之后它不再出水,那我们肯定不会再去按它。为了让我们按按钮的总次数尽量少,我们需要不去按下已经不出水的按钮。

一个显然的策略是一轮按下所有还出水的按钮即\(a_i\gt now\)\(now\)为已经按下的次数。

为了方便维护\(a_i>now\),我们可以将\(a\)升序排序,如果\(a_i\le now\),我们可以把\(i\)往后挪直达\(a_j>now\)

观察到\(a_i\le10^9\),不能一轮一轮模拟,需要使用除法加速。

代码实现

void solve()
{
    ll n, k;
    cin >> n >> k;
    vl a(n);
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    sort(all(a)); // 将罐子数量排序
    ll len = n; // 剩余槽位数量
    ll ans = 0; // 按钮按下的总次数
    ll now = 0; // 当前获得的柠檬水数量
    int i = 0; // 当前槽位索引

    while (k)
    {
        // 处理当前槽位
        while (a[i] <= now) // 如果当前槽位的罐子数量小于等于已获得的数量
        {
            i++;
            ans++; // 按下按钮
            len--; // 剩余槽位数量减少
        }

        // 计算当前槽位能提供的柠檬水
        if (k >= len) // 如果我们需要的数量大于或等于剩余槽位数量
        {
            ll t = k / len; // 每个槽位至少要按下 t 次
            ll cnt = min(t, a[i] - now); // 当前槽位能提供的数量
            ans += cnt * len; // 计算总的按钮按下次数
            now += cnt; // 更新已获得的数量
            k -= cnt * len; // 更新还需的数量
        }
        else // 如果需要的数量小于剩余槽位数量
        {
            ans += k; // 直接按下 k 次
            k = 0; // 更新还需的数量
        }
    }
    cout << ans << endl; // 输出结果
}


C. Concatenation of Arrays

时间限制:每个测试 2 秒

内存限制:每个测试 256 兆字节

输入:标准输入

输出:标准输出

给定 \(n\) 个数组 \(a_1, \ldots, a_n\)。每个数组的长度为 \(2\),因此 \(a_i = [a_{i,1}, a_{i,2}]\)。您需要将这些数组连接成一个长度为 \(2n\) 的数组,以使结果数组中的逆序对数量最小化。请注意,您不需要计算实际的逆序对数量。

更正式地说,您需要选择一个长度为 \(n\) 的排列 \(p\),以便数组 \(b = [a_{p_1,1}, a_{p_1,2}, a_{p_2,1}, a_{p_2,2}, \ldots, a_{p_n,1}, a_{p_n,2}]\) 包含尽可能少的逆序对。

逆序对的定义是:数组 \(c\) 中的逆序对数量是索引对 \(i\)\(j\) 的数量,使得 \(i < j\)\(c_i > c_j\)

一个长度为 \(n\) 的排列是一个由 \(n\) 个不同整数组成的数组,这些整数从 \(1\)\(n\) 以任意顺序排列。例如, \([2,3,1,5,4]\) 是一个排列,但 \([1,2,2]\) 不是一个排列(\(2\) 在数组中出现了两次), \([1,3,4]\) 也不是排列(\(n=3\) 但是数组中有 \(4\))。

输入

每个测试由多个测试用例组成。第一行包含一个整数 \(t\) (\(1 \leq t \leq 10^4\)) — 测试用例的数量。测试用例的描述如下。

每个测试用例的第一行包含一个整数 \(n\) (\(1 \leq n \leq 10^5\)) — 数组的数量。

接下来的每一行包含两个整数 \(a_{i,1}\)\(a_{i,2}\) (\(1 \leq a_{i,j} \leq 10^9\)) — 第 \(i\) 个数组的元素。

保证所有测试用例的 \(n\) 的总和不超过 \(10^5\)

输出

对于每个测试用例,输出 \(2n\) 个整数 — 您获得的数组的元素。如果有多个解决方案,则输出其中任何一个。

示例

输入

4
2
1 4
2 3
3
3 2
4 3
2 1
5
5 10
2 3
9 6
4 1
8 7
1
10 20

输出

2 3 1 4
2 1 3 2 4 3
4 1 2 3 5 10 8 7 9 6
10 20

注意

在第一个测试用例中,我们以顺序 \(2, 1\) 连接数组。考虑结果数组 \(b = [2, 3, 1, 4]\) 中的逆序对:

  • \(i=1, j=3\),因为 \(b_1=2 > 1=b_3\)
  • \(i=2, j=3\),因为 \(b_2=3 > 1=b_3\)

因此,逆序对的数量是 \(2\)。可以证明这是可能的最小逆序对数量量。

在第二个测试用例中,我们以顺序 \(3, 1, 2\) 连接数组。考虑结果数组 \(b = [2, 1, 3, 2, 4, 3]\) 中的逆序对:

  • \(i=1, j=2\),因为 \(b_1=2 > 1=b_2\)
  • \(i=3, j=4\),因为 \(b_3=3 > 2=b_4\)
  • \(i=5, j=6\),因为 \(b_5=4 > 3=b_6\)

因此,逆序对的数量是 \(3\)。可以证明这是可能的最小逆序对数量量。

在第三个测试用例中,我们以顺序 \(4, 2, 1, 5, 3\) 连接数组。

解题思路

为了确保连接后的数组尽可能减少逆序对数量,我们按以下规则进行排序。

  1. 最小值优先:首先根据每个数组的最小值进行排序,可以确保在连接数组时,较小的元素会出现在前面,从而减少后面元素大于前面元素的情况。

  2. 最大值次之:如果两个数组的最小值相同,则根据最大值进行排序。这是为了在最小值相同的情况下,进一步控制元素的相对顺序,确保较大的元素不会在较小元素之前出现。

考虑两个数组 $ a = [x_1, y_1] $ 和 $ b = [x_2, y_2] $,其中 $ x_1 \leq y_1 $ 和 $ x_2 \leq y_2 $。

  • 排序依据
    • 如果 $ x_1 < x_2 $,那么在连接时 $ x_1 $ 会在 $ x_2 $ 之前,减少逆序对。
    • 如果 $ x_1 = x_2 $,那么需要看 $ y_1 $ 和 $ y_2 $ 的大小:
      • 如果 $ y_1 < y_2 $,那么连接后 $ y_1 $ 会在 $ y_2 $ 之前,继续减少逆序对。
      • 如果 $ y_1 \geq y_2 $,则可能会增加逆序对,但由于最小值相同,造成的影响相对较小。

假设我们有以下数组:

  • $ a_1 = [1, 4] $
  • $ a_2 = [2, 3] $

如果我们不进行排序,直接连接可能得到 $ [1, 4, 2, 3] $,这里会有逆序对(例如 $ 4 > 2 $ 和 $ 4 > 3 $),逆序对数量较多。

如果我们按照最小值排序,得到的顺序是 $ a_2, a_1 $,连接后得到 $ [2, 3, 1, 4] $,这样逆序对数量明显减少。

代码实现

void solve()
{
    int n;
    cin >> n;
    vpii a(n);
    for (int i = 0; i < n; ++i)
    {
        cin >> a[i].ft >> a[i].sd;
    }
    sort(all(a), [&](const pii &x, const pii &y)
         {
        if(min(x.ft, x.sd) != min(y.ft, y.sd))
            return min(x.ft, x.sd) < min(y.ft, y.sd);
            return max(x.ft, x.sd) < max(y.ft, y.sd); });
    for (int i = 0; i < n; ++i)
    {
        cout << a[i].ft << " " << a[i].sd << " \n"[i == n - 1];
    }
}

D. Skipping

时间限制:每个测试 2 秒

内存限制:每个测试 256 兆字节

输入:标准输入

输出:标准输出

现在已经是3024年,题目的想法早已用尽,奥林匹克竞赛现在以经过修改的个人形式举行。奥林匹克竞赛由 \(n\) 个问题组成,编号从 \(1\)\(n\)。第 \(i\) 个问题有自己的分数 \(a_i\) 和特定参数 \(b_i\) (\(1 \leq b_i \leq n\))。

最初,测试系统会给参与者第一个问题。当参与者得到第 \(i\) 个问题时,他们有两个选择:

  1. 提交问题并获得 \(a_i\) 分;
  2. 跳过这个问题,在这种情况下他们将永远无法提交它。

然后,测试系统从索引为 \(j\) 的问题中为参与者选择下一个问题:

  • 如果他提交了第 \(i\) 个问题,则查看索引为 \(j < i\) 的问题;
  • 如果他跳过了第 \(i\) 个问题,则查看索引为 \(j \leq b_i\) 的问题。

在这些问题中,它选择索引为最大的问题,该问题以前没有给过参与者(他以前既没有提交过也没有跳过过)。如果没有这样的问题,则参与者的比赛结束,他们的结果等于所有提交问题的分数总和。特别是,如果参与者提交了第一个问题,则他们的比赛结束。请注意,参与者最多收到每个问题一次。

Prokhor 已经为奥林匹克竞赛做好了充分的准备,现在他可以提交任何问题。帮助他确定他可以获得的最高分数。

输入

每个测试由多个测试用例组成。第一行包含一个整数 \(t\) (\(1 \leq t \leq 10^5\)) — 测试用例的数量。测试用例的描述如下。

每个测试用例的第一行包含一个整数 \(n\) (\(1 \leq n \leq 4 \cdot 10^5\)) — 奥林匹克竞赛中的问题数量。

第二行包含 \(n\) 个整数 \(a_1, a_2, \ldots, a_n\) (\(1 \leq a_i \leq 10^9\)) — 问题的分数。

第三行包含 \(n\) 个整数 \(b_1, b_2, \ldots, b_n\) (\(1 \leq b_i \leq n\)) — 问题的参数。

保证所有测试用例的 \(n\) 的总和不超过 \(4 \cdot 10^5\)

输出

对于每个测试用例,输出一个整数——Prokhor 可以获得的最大分数。

示例

输入

4
2
15 16
2 1
5
10 10 100 100 1000
3 4 1 1 1
3
100 49 50
3 2 2
4
100 200 300 1000
2 3 4 1

输出

16
200
100
1000

注意

在第一个测试用例中,Prokhor 可以跳过第一个问题;然后他将收到索引为 \(b_1=2\) 的问题。Prokhor 可以提交它并获得 \(a_2=16\) 分。之后,比赛将结束,因为 Prokhor 已经收到所有问题。请注意,如果 Prokhor 提交第一个问题,他将获得 \(a_1=15\) 分,但比赛会立即结束。

在第二个测试用例中,Prokhor 可以跳过第一个问题;然后他将收到索引为 \(b_1=3\) 的问题。Prokhor 可以提交它并获得 \(a_3=100\) 分。之后,Prokhor 将收到第二个问题,他可以跳过以接收索引为 \(b_2=4\) 的问题。Prokhor 可以提交第四个问题并获得另一个 \(a_4=100\) 分。之后,比赛结束,因为 Prokhor 已经收到所有索引不超过 \(4\) 的问题。因此,Prokhor 将获得总共 \(200\) 分。

在第三个测试用例中,Prokhor 可以提交第一个问题并获得 \(100\) 分,之后比赛会立即结束。

解题思路

观察题目发现,我们最优的策略一定是经过一系列点\(p_1,p_2,p_3\dots p_m\)到达\(p_m\)后停下,然后在\(p_m\)跳转到所有\(i\notin P,i<p_m\)的点上获取它们的分数,且\(\forall i\lt m,p_i\lt p_m\)。如果\(\exist p_j\gt p_m\)那我们在\(p_j\)停下一定不劣于在\(p_m\)停下。

答案\(\text{ans}=\text{min}( \text{prefix}_{p_m}-\sum^{m}_{i=1}a_{p_i}),1\le p_m\le n\)

所以我们可以建图,然后跑最短路,算出到达每一个点的最小花费。

对于第一种操作,对\(i\rightarrow i-1\)建边,其边权为\(0\)

对于第二种操作,对\(i\rightarrow b_i\)建边,其边权为\(a_i\)

然后跑一遍dijkstra算出到达每一个点的最小代价

然后枚举所有可能的终点即可。

这题还有dp的做法,我有空补补。

代码实现

void solve()
{
    int n;
    cin >> n;
    vi a(n + 1);
    vl pre(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        pre[i] = pre[i - 1] + a[i];
    }
    vi b(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> b[i];
    }
    vvi adj(n + 1);
    vvl w(n + 1);
    for (int i = 1; i <= n; i++)
    {
        adj[i].pb(b[i]);
        w[i].pb(a[i]);
        if (i != 1)
        {
            adj[i].pb(i - 1);
            w[i].pb(0);
        }
    }
    vl dis(n + 1, infll);
    vb vis(n + 1);
    dis[1] = 0;
    auto dijkstra = [&]()
    {
        priority_queue<pll, vpll, greater<pll>> q;
        q.push({0, 1});
        while (!q.empty())
        {
            auto t = q.top();
            q.pop();
            ll d = t.ft;
            int u = t.sd;
            if (vis[u])
                continue;
            vis[u] = true;
            for (int i = 0; i < adj[u].size(); i++)
            {
                int v = adj[u][i];
                ll cost = d + w[u][i];
                if (dis[v] > cost)
                {
                    dis[v] = cost;
                    q.push({cost, v});
                }
            }
        }
    };
    dijkstra();
    ll ans = 0;
    for (int i = 1; i <= n; i++)
    {
        ans = max(ans, pre[i] - dis[i]);
    }
    cout << ans << endl;
}

E不会写,看不懂一点,最近这几场掉大分,本来差12分上紫,结果狂掉270分,差点掉出蓝了,场场卡B和C,导致没时间写后面的了,人快麻了。

posted @ 2024-10-21 04:14  ExtractStars  阅读(699)  评论(1编辑  收藏  举报