第十四届蓝桥杯题解C ~ I

目录

C:冶炼金属​编辑

D:飞机降落

E:接龙数列

F:岛屿个数​编辑

G: 子串简写

H: 整数删除

I: 景区导游


C:冶炼金属

 推公式或者二分, 下面是二分做法

#include<iostream>
using namespace std;
int main()
{
    int n;
    cin >> n;
    int mx = 1e9, mn = 0;
    for (int i = 1; i <= n; i ++ ) {
        int a, b;
        cin >> a >> b;
        mx = min(mx, a / b);
        int l = 0, r = mx;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (mid * (b + 1) < a) l = mid;
            else r = mid - 1;
        }
        while (l * (b + 1) <= a) l ++ ;
        mn = max(mn, l);
    }
    cout << mn << ' ' << mx << endl;
    
    return 0;
}

D:飞机降落

      【评测用例规模与约定】 对于 30% 的数据,N ≤ 2。 对于 100% 的数据,1 ≤ T ≤ 10,1 ≤ N ≤ 10,0 ≤ Ti , Di , Li ≤ 105。

根据数据范围和时间限制, T * 10!= 3,628,8000 暴力枚举降落顺序即可(可以采用暴搜或者

next_permutation() 函数暴力枚举)

注意:贪心排序是错误做法,因为可以最晚降落时间可以很长,但是可以骗取一定分数

下面是dfs代码

#include<iostream>
#include<cstring>
using namespace std;
int t[20], d[20], l[20];
int n, m;
bool st[20];
bool dfs(int u, int s) {
    if (u > n) return true;
    for (int i = 1; i <= n; i ++ ) {
        if (!st[i]) {
            st[i] = true;
            if (t[i] + d[i] >= s) {
                if (dfs(u + 1, max(t[i] + l[i], s + l[i]))) return true;
            }
            st[i] = false;
        }
    }
    return false;
}
void solve() {
    memset(st, 0, sizeof st);
    cin >> n;
    for (int i = 1; i <= n; i ++ ) cin >> t[i] >> d[i] >> l[i];
    if (dfs(1, 0)) cout << "YES" << endl;
    else cout << "NO" << endl;
}
int main()
{
    int t;
    cin >> t;
    while (t -- ) {
        solve();
    }
    return 0;
}

E:接龙数列

【评测用例规模与约定】 对于 20% 的数据,1 ≤ N ≤ 20。 对于 50% 的数据,1 ≤ N ≤ 10000。 对于 100% 的数据,1 ≤ N ≤ 105,1 ≤ Ai ≤ 109。所有 Ai 保证不包含前导 0。

数据范围很大,采用O(n) 或者 O(nlogn) 做法,但是观察发现首位数和末尾数只有10种,采用线性dp即可,时间复杂度O(n)

#include <iostream> 
using namespace std;
int f[10];
int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        string s;
        cin >> s;
        int m = s.size();
        f[s[m - 1] - '0'] = max(f[s[m - 1] - '0'], f[s[0] - '0'] + 1);
    }
    int res = 0;
    for (int i = 0; i < 10; i ++ )
        res = max(res, f[i]);
    cout << n - res;
    return 0;
}

F:岛屿个数

俩遍BFS

第一遍 BFS, 从(0, 0)开始扩展, 把所有能扩展到的岛屿标记

第二遍 BFS, 把所有被标记的岛屿的联通岛屿找出来计数即可

#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#define x first
#define y second 
#define endl '\n'
#define NOCOM std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0)
#define rge(i, x, y) for (int i = x; i <= y; i ++ )
// #define int long long
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
constexpr int N = 1e5 + 10;
bool st[60][60], ok[60][60];
char mp[60][60];
int n, m;
int dx[8] {0, 1, 0, -1, - 1, - 1, 1, 1}, dy[] {1, 0, -1, 0, -1, 1, -1, 1};

void bfs() {
    queue<PII> q;
    q.push({0, 0});
    while (q.size()) {
        auto [x, y] = q.front();
        q.pop();
        rge(i, 0, 7) {
            int px = x + dx[i], py = y + dy[i];
            if (px < 0 || py < 0 || px > n + 1 || py > m + 1) continue;
            if (mp[px][py] == '0' && !st[px][py]) q.push({px, py});
            st[px][py] = true;
        }
    }
}
void solve() {
    memset(st, 0, sizeof st);
    memset(ok, 0, sizeof ok);
    cin >> n >> m;
    rge(i, 0, n + 1) rge(j, 0, m + 1) mp[i][j] = '0';
    rge(i, 1, n) rge(j, 1 ,m) cin >> mp[i][j];
    bfs();
    int res = 0;
    auto GetTog = [&](int i, int j) -> void {
        queue<PII> q;
        q.push({i, j}), ok[i][j] = true;
        while (q.size()) {
            auto [x, y] = q.front();
            q.pop();
            rge(i, 0, 3) {
                int px = x + dx[i], py = y + dy[i];
                if (px < 1 || py < 1 || px > n || py > m) continue;
                if (mp[px][py] == '1' && !ok[px][py]) 
                    q.push({px, py}), ok[px][py] = true;
            }
        }
    };
    rge(i, 1, n) rge(j, 1, m) 
        if (st[i][j] && !ok[i][j] && mp[i][j] == '1') 
            GetTog(i, j), res ++ ;


    cout << res << endl;
}

signed main() {
    NOCOM;
    int t;
    cin >> t;
    rge(i, 1, t) solve();

    return 0;
}

G: 子串简写

 这题比之前几题简单

O(n)做法采用前缀和

O(nlogn)做法采用二分计算即可

下面是二分代码:

注意:二分有边界问题,对vector判断是否为空,防止CE

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    int k;
    char a, b;
    string s;
    cin >> k >> s >> a >> b;
    vector<int> p;
    int n = s.size();
    long long res = 0;
    for (int i = 0; i < n; i ++ ) {
        if (s[i] == a) p.push_back(i);
        if (s[i] == b && p.size()) {
            int l = 0, r = p.size() - 1;
            while (l < r) {
                int mid = l + r >> 1;
                if (p[mid] >= i - k + 1) r = mid;
                else l = mid + 1;
            }
            if (p[l] > i - k + 1) {
                if (l != 0) res += l;
            } else res += l + 1;
        }
    }
    cout << res << endl; 
    return 0;
}

H: 整数删除

数据结构题,采用数组模拟链表+平衡树或者优先队列模拟即可

#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#define x first
#define y second 
#define endl '\n'
#define NOCOM std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0)
#define rge(i, x, y) for (int i = x; i <= y; i ++ )
#define int long long
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
constexpr int N = 5e5 + 10;
int n, m, a[N];
int ne[N], pre[N], idx = 1, h = 1;
set<PII> st;
void solve() {
    cin >> n >> m;
    rge(i, 1, n) cin >> a[i];
    rge(i, 1, n) {
        pre[i] = i - 1, ne[i] = i + 1;
        st.insert({a[i], i});
    }
    auto erase = [&](int idx, int v) -> void {
        st.erase({a[pre[idx]], pre[idx]});
        st.erase({a[ne[idx]], ne[idx]});
        a[pre[idx]] += v, a[ne[idx]] += v;
        ne[pre[idx]] = ne[idx], pre[ne[idx]] = pre[idx];
        if (ne[idx] <= n) st.insert({a[ne[idx]], ne[idx]});
        if (pre[idx] > 0) st.insert({a[pre[idx]], pre[idx]});
        if (idx == h) h = ne[idx];
    };
    while (st.size() > n - m) {
        auto [v, idx] = *(st.begin());
        erase(idx, v);
        st.erase({v, idx});
    }
    for (int i = h; i <= n; i = ne[i])
            cout << a[i] << " \n"[ne[i] > n];
}

signed main() {
    NOCOM;
    int t = 1;
    // cin >> t;
    rge(i, 1, t) solve();

    return 0;
}

I: 景区导游

 

LCA,倍增求LCA即可

#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <numeric>
#include <climits>
#include <set>
#include <map>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#define x first
#define y second 
#define endl '\n'
#define NOCOM std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0)
#define rge(i, x, y) for (int i = x; i <= y; i ++ )
#define int long long
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
constexpr int N = 1e5 + 10;
int n, m;
vector<PII> h[N];
void solve() {
    cin >> n >> m;
    rge(i, 1, n - 1) {
        int a, b, c;
        cin >> a >> b >> c;
        h[a].emplace_back(b, c);
        h[b].emplace_back(a, c);
    }
    vector<int> a(m + 1), dh(n + 1, INT_MAX), dt(n + 1);
    vector<vector<int>> f(n + 1, vector<int>(21));
    rge(i, 1, m) cin >> a[i];
    auto bfs = [&]() -> void {
        queue<int> q;
        q.push(1), dh[1] = 1, dh[0] = 0;
        while (q.size()) {
            int u = q.front();
            q.pop();
            for (auto [x, v] : h[u]) {
                if (dh[x] > dh[u] + 1) {
                    // cout << u << ' ' << x << ' ' << v << endl;
                    dh[x] = dh[u] + 1;
                    dt[x] = dt[u] + v;
                    f[x][0] = u;
                    q.push(x);
                    rge(i, 1, 20) f[x][i] = f[f[x][i - 1]][i - 1];
                }
            }
        }
    };
    bfs();
    auto get = [&](int a, int b) -> int {
        if (dh[a] < dh[b]) swap(a, b);
        int len = dt[a] + dt[b];
        for (int i = 20; i >= 0; i -- )
            if (dh[f[a][i]] >= dh[b]) a = f[a][i];
        if (a == b) return len - dt[a] * 2;
        for (int i = 20; i >= 0; i -- ) 
            if (f[a][i] != f[b][i])
                a = f[a][i], b = f[b][i];
        return len - dt[f[a][0]] * 2;
    };
    int s = 0;
    rge(i, 2, m) s += get(a[i], a[i - 1]);
    rge(i, 1, m) {
        if (i == 1) cout << s - get(a[1], a[i + 1]) << ' ';
        else if (i == m) cout << s - get(a[m - 1], a[m]) << endl;
        else cout << s - get(a[i - 1], a[i]) - get(a[i + 1], a[i]) + get(a[i - 1], a[i + 1]) << ' ';
    }
}

signed main() {
    NOCOM;
    int t = 1;
    // cin >> t;
    rge(i, 1, t) solve();

    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值