2020, XIII Samara Regional Intercollegiate Programming Contest

2020, XIII Samara Regional Intercollegiate Programming Contest

题目比较简单, 找几个比较难的题讲一下。

B. Bonuses on a Line

题意:

给你一些在x轴上的坐标, 每个坐标都有一些食物, 给你一个时间t, 你每秒钟可以一个单位, 刚开始你在原点(0)问在t秒之后你最多可以获得多少食物?

题解:

A: 这题是枚举状态吧?

B:是的!难点就是你要如何找到所有状态。

A: 如何找到所有状态呢?

B: 因为刚开始在0的位置, 所以先枚举在x轴左边, 最后一次到的点 ,剩下的时间走右边,

同理 , 在枚举x轴的右边最后一次走的点 剩下时间走左边。

A: 那暴力查找会超时呀。

B:这里可以用二分取优化, 查第一个大于就行了。

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int N = 200000 + 7;

ll n, t, a[N];
vector<ll>positive, negative;

int main(){    
    ll ans = 0;
    scanf("%lld %lld", &n, &t);
    for(int i = 1; i <= n; i++){
        scanf("%lld", &a[i]);
        if(a[i] == 0){
            ans++;
        }else if(a[i] > 0){
            positive.push_back(a[i]);
        }else{
            negative.push_back(-a[i]);
        }
    }
    sort(negative.begin(), negative.end());
    positive.push_back(100000000000000);
    negative.push_back(100000000000000);
   
    // positive
    ll cnt = t;
    ll res = 0;
    ll maxn = 0;
    for(int i = 0; i < positive.size() - 1; i++){
        if(cnt >= positive[i]){
            res++;
            ll cn =cnt - positive[i];
            if(cn >= positive[i]){
                ll cat =cn - positive[i];
                int p = upper_bound(negative.begin(), negative.end(), cat) - negative.begin();
                maxn = max(ans + res + p, maxn);

            }
        }else{
            break;
        }
    }
    maxn = max(maxn, res + ans);

    // negative
    res = 0;
    cnt = t;
    for(int i = 0; i < negative.size() - 1; i++){
        if(cnt >= negative[i]){
            ll cn =cnt - negative[i];
            res++;
            if(cn >= negative[i]){
                ll cat = cn - negative[i];
                int p = upper_bound(positive.begin(), positive.end(), cat) - positive.begin();
                maxn = max(ans + res + p, maxn);
            }
        }else{
            break;
        }
    }
    maxn = max(ans + res, maxn);
    printf("%lld
", maxn);


}   

D. Lexicographically Minimal Shortest Path

题意:

给你一张图边权是字符, 问找一个最多路径,如果有多个输出经过的边的字符字典序最小的那个。

题解:

A:这题咋想的?

B: 先求出最短路然后, 找出所有最短路径, 枚举一个字典序最小的。

A: 就是找出所有的最短路径然后再枚举?不会超时吗?

B: 不能直接找出所有的最短路径枚举, 那样肯定会超时!, 我们可以先求出来 到 n的所有点的最短路 ,

如果 有一条边 比如(u, v) dist[u] == dist[v] - 1, 那么(u, v) 这条边就可以做最短路的一条边, 找出所有可能的边,

然后从源点 (1)开始贪心枚举, 要是当前边有一个最小的就走这个, 要是有多个最小的, 就全部都走 , 然后第二层继续枚举, 之前的走的点, 要是有多个最小的也是全部都走, 有一个就走一个, 这样的话时间复杂度最多也就是 o(m).

A:没听懂!!!

B: 我想你看我代码模拟一边会更好。

A: 好的。

#include<bits/stdc++.h>

using namespace std;
const int N = 200007;

vector<pair<int, char> > g[N];

int n, m, dist[N];

queue<pair<int, int> > q;

void bfs(){
    q.push({n, 0});
    memset(dist, -1, sizeof(dist));
    while (q.size()){
        auto cd = q.front();
        q.pop();
        if (dist[cd.first] != -1) continue;
        dist[cd.first] = cd.second;
        for (auto it: g[cd.first]) {
            int to = it.first;
            q.push({to, cd.second + 1});
        }
    }
}

int vis[N];
vector<int>Q;
vector<int> ans;
int fa[N];

void path(int x){
    if(x == 0) return;
    path(fa[x]);
    printf("%d ", x);
}

int main(){
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int u, v;
        char w;
        scanf("%d %d %c", &u, &v, &w);
        g[u].push_back({v, w});
        g[v].push_back({u, w});
    }
    bfs();
    Q.push_back(1);
    for (int i = 1; i <= dist[1]; i++) {
        int minn = 1000;
        vector<int> v;
        for(int cd: Q) {
            for (auto it: g[cd]){
                int to = it.first;
                int cost = (int)it.second;
                if (dist[to] + 1 == dist[cd])
                    minn = min(minn, cost);
            }
        }
        for(int cd: Q){
            for (auto it: g[cd]){
                int to = it.first;
                int cost = (int)it.second;
                if (dist[to] + 1 == dist[cd]) {
                    if (cost == minn && vis[to] == 0) {
                        v.push_back(to);
                        fa[to] = cd;
                        vis[to] = 1;
                    }
                }
            }
        }

        ans.push_back(minn);
        Q.clear();
        for(int j: v){
            Q.push_back(j);
        }

    }

    printf("%d
", (int)ans.size());
    path(n);
    puts("");
    for(int i: ans){
        printf("%c", (char)i);
    }
    puts("");
    
}
原文地址:https://www.cnblogs.com/BOZHAO/p/13264529.html