2024西北师范大学天梯赛选拔赛 题解

author : 星幻流空

A题:思路:

按照题意直接输出即可。

void solve()
{
    int n;
    cin >> n;
    if (n < 400) cout << "这活干不了一点了!";
    else if (n > 600) cout << "我要加倍干!";
    else cout << "这活我干的不亏";
}

B题:思路:

本次 B 题的测试用例存在错误,因此不予讲解。

C题:思路:

判断字符串的序列的 dfs 的数量,使用 标记,达到数量 + 1 即可

void solve()
{
    int n;
    cin >> n;
    string s;
    cin >> s;
    int f = 1;
    int ans = 0;
    for (int i = 0; i < n; i ++ ){
        if (f == 1 && s[i] == 'd'){
            f = 2;
        }
        if (f == 2 && s[i] == 'f'){
            f = 3;
        }
        if (f == 3 && s[i] == 's'){
            f = 1;
            ans ++ ;
        }
    }
     
    cout << ans << endl;
}

D题:思路:

前缀和,计算一段区间的值,使用前缀和预处理即可。

void solve()
{
    int n, m;
    cin >> n >> m;
     
    int a[n + 1] = {0};
    for (int i = 1; i <= n; i ++ ){
        cin >> a[i];
        a[i] += a[i - 1];
    }
     
    while (m -- ){
        int x, y;
        cin >> x >> y;
        cout << a[y] - a[x - 1] << endl;
    }
}

E题:思路:

字符串的缝合,使用substr函数操作直接实现即可。

void solve()
{
    string s;
    cin >> s;
     
    int n;
    cin >> n;
     
    while (n -- ){
        int a, b;
        string x, y;
        cin >> a >> b >> x >> y;
         
        string t = s.substr(a, b - a + 1); // 剪切字符串
        int idx = s.find(x + y); // 寻找插入位置
         
        if (idx == -1){ // 不存在插入末尾
            s += t;
            continue;
        }
        else { // 存在插入到指定位置
            idx += x.size();
            s = s.substr(0, idx) + t + s.substr(idx, s.size() - 1);
        }
    }
    
    cout << s << endl;  
}

F题:思路:

并查集,和中病毒感染者一个集合的都中病毒。

const int N = 1e3 + 10;
 
int p[N];
int n, m;

// 初始化
void init(){
    for (int i = 0; i <= n - 1; i ++ ){
        p[i] = i;
    }
}
 
// 查找
int find(int x){
    if (x != p[x]){
        p[x] = find(p[x]);
    }
    return p[x];
}

// 合并集合
bool merge(int x, int y){
    x = find(x), y = find(y);
    if (x == y){
        return 1;
    }
    p[x] = y;
    return 0;
}
 
void solve()
{
    init();
    while (m -- ){
        int k, idx;
        cin >> k;
        for (int i = 0; i < k; i ++ ){
            int t;
            cin >> t;
            if (i == 0) {
                idx = t;
                continue;   
            }
            merge(t, idx); // 默认都合并到第一个节点
        }
    }
    
    int ans = 0;
    for (int i = 1; i < n; i ++ ){
        if (find(i) == find(0)){ // 和 0 在一个集合,则中病毒
            ans ++ ;
        }
    }
     
    cout << ans + 1 << endl; // 也包括 0 因此 + 1
}

G题:思路:

map存储 相应的时间花钱,最后重新放在vector中进行排序即可。

void solve()
{
    int n, m;
    cin >> n >> m;
     
    map<string, int> ma;
    int ans = 0, sum = 0;
     
    for (int i = 0; i < n; i ++ ){
        string s;
        int x;
         
        cin >> s >> x;
         
        if (x >= m){
            ma[s] += 50;
            sum += 50;
        }
        else if (x < 60){
            ans ++ ;
        }
        else {
            ma[s] += 20;
            sum += 20;
        }
    }
    cout << sum << endl;
    if (ans >= 5) {
        cout << "(>﹏<)" << endl;
        return ;
    }
     
    vector<pair<string, int> > v;
     
    for (auto i : ma){ // map 存储到 vector 中
        v.push_back({i.first, i.second});
    }
     
    sort(v.begin(), v.end(), [&](PII x, PII y){
        if (x.second != y.second){ // 优先金钱排序
            return x.second > y.second;
        }
        else { // 其次时间排序
            return x.first < y.first;
        }
    });
     
    for (auto i : v){
        cout << i.first << " " << i.second << endl;
    }
     
}

H题:思路:

dijkstra 最简单的模板。

void solve()
{
    int n, m, s;
    cin >> n >> m >> s;
     
    vector<vector<PII> > g(n + 1);
    for (int i = 0; i < m; i ++ ){
        int u, v, w;
        cin >> u >> v >> w;
         
        g[u].push_back({w, v});
    }
     
    int d[n + 1];
    memset(d, 0x3f, sizeof(d));
    bool st[n + 1] = {false};
     
    priority_queue<PII, vector<PII>, greater<PII> > q;
     
    d[s] = 0;
    q.push({0, s});
     
    while (!q.empty()){
        auto t = q.top();
        int dist = t.first, x = t.second;
        q.pop();
         
        if (st[x]) continue;
        st[x] = true;
         
        for (int i = 0; i < g[x].size(); i ++ ){
            int j = g[x][i].second, p = g[x][i].first;
            d[j] = min (d[j], d[x] + p);
            q.push({d[j], j});
        }
         
    } 
     
    for (int i = 1; i <= n; i ++ ){
        cout << d[i] << " ";
    }
}