国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

2023第十四屆藍(lán)橋杯C/C++B組省賽題解

這篇具有很好參考價(jià)值的文章主要介紹了2023第十四屆藍(lán)橋杯C/C++B組省賽題解。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

2023藍(lán)橋C/C++B組省賽

試題A: 日期統(tǒng)計(jì)

題目描述

【問題描述】
小藍(lán)現(xiàn)在有一個(gè)長(zhǎng)度為100 的數(shù)組,數(shù)組中的每個(gè)元素的值都在0 到9 的范圍之內(nèi)。數(shù)組中的元素從左至右如下所示:

5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3 3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1 0 0 9 4 8 0 9 1 2 8 5 0 2 5 3 3

現(xiàn)在他想要從這個(gè)數(shù)組中尋找一些滿足以下條件的子序列:

  1. 子序列的長(zhǎng)度為8;

  2. 這個(gè)子序列可以按照下標(biāo)順序組成一個(gè)yyyymmdd 格式的日期,并且
    要求這個(gè)日期是2023 年中的某一天的日期,例如20230902,20231223。yyyy 表示年份,mm 表示月份,dd 表示天數(shù),當(dāng)月份或者天數(shù)的長(zhǎng)度只有一位時(shí)需要一個(gè)前導(dǎo)零補(bǔ)充。

請(qǐng)你幫小藍(lán)計(jì)算下按上述條件一共能找到多少個(gè)不同的2023 年的日期。
對(duì)于相同的日期你只需要統(tǒng)計(jì)一次即可。

枚舉

用八重循環(huán)直接枚舉每一位數(shù)字, 題目中的日期序列有很多限制, 如前四位必須是2023, 又比如月份只能以0或1開頭等等。利用這些限制能大大降低運(yùn)行時(shí)間, 實(shí)測(cè)只要限制了前四位, 基本是瞬間跑出結(jié)果。

注意需要用哈希表去重。

參考代碼

//
// Created by trudbot on 2023/4/9.
//

#include <bits/stdc++.h>
using namespace std;
int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
set<int> res;

void check(int m, int d) {
    if (m < 1 || m > 12 || d < 1 || d > days[m]) return;
    res.insert(m * 100 + d);
}

int main () {
    int ns[100];
    for (int & n : ns) cin >> n;
    for (int a = 0; a < 100; a ++) {
        if (ns[a] != 2) continue;
        for (int b = a + 1; b < 100; b ++) {
            if (ns[b] != 0) continue;
            for (int c = b + 1; c < 100; c ++) {
                if (ns[c] != 2) continue;
                for (int d = c + 1; d < 100; d ++) {
                    if (ns[d] != 3) continue;

                    for (int i = d + 1; i < 100; i ++)
                        for (int j = i + 1; j < 100; j ++)
                            for (int k = j + 1; k < 100; k ++)
                                for (int l = k + 1; l < 100; l ++)
                                    check(ns[i] * 10 + ns[j], ns[k] * 10 + ns[l]);
                }
            }
        }
    }
    cout << res.size() << endl;
    return 0;
}
//in: 5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2
//7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3 3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1
//0 0 9 4 8 0 9 1 2 8 5 0 2 5 3 3
//out: 235

試題B: 01 串的熵

題目描述

對(duì)于一個(gè)長(zhǎng)度為n 的01 串 S = x 1 x 2 x 3 . . . x n S = x_1x_2x_3...x_n S=x1?x2?x3?...xn?,香農(nóng)信息熵的定義為 H ( S ) = ? ∑ 1 n p ( x i ) log ? 2 ( p ( x i ) ) H(S ) = ?\sum^n_1p(x_i) \log_2(p(x_i)) H(S)=?1n?p(xi?)log2?(p(xi?)),其中 p ( 0 ) , p ( 1 ) p(0),p(1) p(0),p(1) 表示在這個(gè)01 串中0 和1 出現(xiàn)的占比。

比如,對(duì)于S = 100 來說,信息熵 H ( S ) = ? 1 3 log ? 2 ( 1 3 ) ? 2 3 log ? 2 ( 2 3 ) ? 2 3 log ? 2 ( 2 3 ) = 1.3083 H(S ) = ?\frac13 \log_2( \frac13 ) ? \frac23 \log_2( \frac23 ) ? \frac23 \log_2( \frac23 )=1.3083 H(S)=?31?log2?(31?)?32?log2?(32?)?32?log2?(32?)=1.3083。對(duì)于一個(gè)長(zhǎng)度為23333333 的01 串,如果其信息熵為11625907.5798,且0 出現(xiàn)次數(shù)比1 少,那么這個(gè)01 串中0 出現(xiàn)了多少次?

枚舉|模擬

設(shè)01字符串S長(zhǎng)度為n, 0的個(gè)數(shù)為x。

p ( 0 ) = x n , p ( 1 ) = n ? x n p(0) = \frac xn, p(1) = \frac{n-x}{n} p(0)=nx?,p(1)=nn?x?.

H ( S ) = ? ∑ 1 n p ( x i ) log ? 2 ( p ( x i ) ) = ? ( x p ( 0 ) log ? 2 ( p ( 0 ) ) + ( n ? x ) p ( 1 ) log ? 2 ( p ( 1 ) ) ) H(S ) =?\sum^n_1p(x_i) \log_2(p(x_i)) = -(xp(0)\log_2(p(0)) + (n-x)p(1)\log_2(p(1))) H(S)=?1n?p(xi?)log2?(p(xi?))=?(xp(0)log2?(p(0))+(n?x)p(1)log2?(p(1)))

在已知n, x時(shí), 計(jì)算H是 O ( 1 ) O(1) O(1)的, 所以只需要枚舉x即可。

參考代碼

//
// Created by trudbot on 2023/4/9.
//

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll H = 116259075798;
const ll N = 23333333;

bool check(ll x) {
    double p0 = x * 1.0 / N, p1 = 1 - p0;
    ll h = 10000ll * (x * p0 * log2(p0) + (N - x) * p1 * log2(p1));
    return h + H == 0;
}

int main () {
    for (int x = 1; x <= N / 2; x ++) {
        if (check(x)) cout << x << endl;
    }
    return 0;
}
//out: 11027421

試題C: 冶煉金屬

題意描述

小藍(lán)有一個(gè)神奇的爐子用于將普通金屬O 冶煉成為一種特殊金屬X。這個(gè)爐子有一個(gè)稱作轉(zhuǎn)換率的屬性V,V 是一個(gè)正整數(shù),這意味著消耗V 個(gè)普通金屬O 恰好可以冶煉出一個(gè)特殊金屬X,當(dāng)普通金屬O 的數(shù)目不足V 時(shí),無法繼續(xù)冶煉。

現(xiàn)在給出了N 條冶煉記錄,每條記錄中包含兩個(gè)整數(shù)A 和B,這表示本次投入了A 個(gè)普通金屬O,最終冶煉出了B 個(gè)特殊金屬X。每條記錄都是獨(dú)立的,這意味著上一次沒消耗完的普通金屬O 不會(huì)累加到下一次的冶煉當(dāng)中。
根據(jù)這N 條冶煉記錄,請(qǐng)你推測(cè)出轉(zhuǎn)換率V 的最小值和最大值分別可能是多少,題目保證評(píng)測(cè)數(shù)據(jù)不存在無解的情況。

取交集

對(duì)于每一條記錄, 都可以求出轉(zhuǎn)換率V的一個(gè)取值范圍。 V必須滿足所有記錄求出的取值范圍, 所以只需要對(duì)N個(gè)區(qū)間求交集即可, 也就是右邊界取所有右邊界的最小值, 左邊界取所有左邊界的最大值。。

參考代碼

//
// Created by trudbot on 2023/4/9.
//

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

int main () {
    int n; cin >> n;
    int mn = -1, mx = 1e9;
    while (n --) {
        int a, b; cin >> a >> b;
        int l = a / (b + 1) + 1, r = a / b;
        mn = max(mn, l), mx = min(mx, r);
    }
    cout << mn << " " << mx << endl;
    return 0;
}

試題D: 飛機(jī)降落

題意描述

N 架飛機(jī)準(zhǔn)備降落到某個(gè)只有一條跑道的機(jī)場(chǎng)。其中第i 架飛機(jī)在 T i T_i Ti? 時(shí)刻到達(dá)機(jī)場(chǎng)上空,到達(dá)時(shí)它的剩余油料還可以繼續(xù)盤旋 D i D_i Di? 個(gè)單位時(shí)間,即它最早可以于 T i T_i Ti? 時(shí)刻開始降落,最晚可以于 T i + D i T_i + D_i Ti?+Di? 時(shí)刻開始降落。降落過程需要 L i L_i Li?
個(gè)單位時(shí)間。

一架飛機(jī)降落完畢時(shí),另一架飛機(jī)可以立即在同一時(shí)刻開始降落,但是不能在前一架飛機(jī)完成降落前開始降落。

請(qǐng)你判斷N 架飛機(jī)是否可以全部安全降落。

DFS+剪枝, 懶得寫

試題E: 接龍數(shù)列

題意描述

對(duì)于一個(gè)長(zhǎng)度為K 的整數(shù)數(shù)列: A 1 , A 2 . . A K A_1,A_2..A_K A1?,A2?..AK?,我們稱之為接龍數(shù)列當(dāng)且僅當(dāng) A i A_i Ai? 的首位數(shù)字恰好等于 A i ? 1 A_{i?1} Ai?1? 的末位數(shù)字(2 ≤ i ≤ K)。

例如 12 , 23 , 35 , 56 , 61 , 11 12,23,35,56,61,11 12,23,35,56,61,11 是接龍數(shù)列; 12 , 23 , 34 , 56 12,23,34,56 12,23,34,56 不是接龍數(shù)列,因?yàn)?6的首位數(shù)字不等于34 的末位數(shù)字。所有長(zhǎng)度為1 的整數(shù)數(shù)列都是接龍數(shù)列。

現(xiàn)在給定一個(gè)長(zhǎng)度為N 的數(shù)列 A 1 , A 2 . . . A N A_1,A_2... A_N A1?,A2?...AN?,請(qǐng)你計(jì)算最少從中刪除多少個(gè)數(shù),可以使剩下的序列是接龍序列?

DP

要求使得數(shù)列變成接龍數(shù)列的最少刪除個(gè)數(shù), 相當(dāng)于求該數(shù)列的最長(zhǎng)接龍子數(shù)列的長(zhǎng)度, 用總長(zhǎng)度減去最長(zhǎng)接龍長(zhǎng)度即為最少刪除個(gè)數(shù)。

定義 d p [ i ] [ j ] dp[i][j] dp[i][j]為前i個(gè)數(shù)中, 以數(shù)字j結(jié)尾的最長(zhǎng)接龍數(shù)列的長(zhǎng)度。

設(shè)第i個(gè)數(shù)的首位數(shù)字是a, 末位數(shù)字是b。 則 d p [ i ] dp[i] dp[i]中相對(duì)于 d p [ i ? 1 ] dp[i-1] dp[i?1]可能發(fā)生變化的只有 d p [ i ] [ b ] dp[i][b] dp[i][b], 因?yàn)榈趇個(gè)數(shù)可能加到一個(gè)以a結(jié)尾的接龍數(shù)列中, 使得這個(gè)接龍數(shù)列長(zhǎng)度加1并且結(jié)尾數(shù)字變成b.

所以狀態(tài)轉(zhuǎn)移方程為dp[i][b] = max(dp[i - 1][b], dp[i - 1][a] + 1)

參考代碼

//
// Created by trudbot on 2023/4/9.
//

#include <bits/stdc++.h>
using namespace std;
int dp[10];

int main () {
    int n, mx = 0; cin >> n;
    for (int i = 0; i < n; i ++) {
        string s; cin >> s;
        int a = s[0] - '0', b = s.back() - '0';
        dp[b] = max(dp[b], dp[a] + 1), mx = max(mx, dp[b]);
    }
    cout << n - mx << endl;
    return 0;
}

試題F: 島嶼個(gè)數(shù)

題意描述

小藍(lán)得到了一副大小為M × N 的格子地圖,可以將其視作一個(gè)只包含字符‘0’(代表海水)和‘1’(代表陸地)的二維數(shù)組,地圖之外可以視作全部是海水,每個(gè)島嶼由在上/下/左/右四個(gè)方向上相鄰的‘1’ 相連接而形成。

在島嶼A 所占據(jù)的格子中,如果可以從中選出k 個(gè)不同的格子,使得他們的坐標(biāo)能夠組成一個(gè)這樣的排列:( x 0 , y 0 x_0, y_0 x0?,y0?),( x 1 , y 1 x_1,y_1 x1?,y1?)… ( x k ? 1 , y k ? 1 x_{k?1}, y_{k?1} xk?1?,yk?1?),其中( x ( i + 1 ) % k , y ( i + 1 ) % k x_{(i+1)}\%k,y_{(i+1)}\%k x(i+1)?%k,y(i+1)?%k) 是由( x i , y i x_i, y_i xi?,yi?) 通過上/下/左/右移動(dòng)一次得來的(0 ≤ i ≤ k ? 1),此時(shí)這k 個(gè)格子就構(gòu)成了一個(gè)“環(huán)”。如果另一個(gè)島嶼B 所占據(jù)的格子全部位于這個(gè)“環(huán)” 內(nèi)部,此時(shí)我們將島嶼B 視作是島嶼A 的子島嶼。若B 是A 的子島嶼,C 又是B 的子島嶼,那C 也是A 的子島嶼。

請(qǐng)問這個(gè)地圖上共有多少個(gè)島嶼?在進(jìn)行統(tǒng)計(jì)時(shí)不需要統(tǒng)計(jì)子島嶼的數(shù)目。

dfs | 連通塊

本題有兩種類型的頂點(diǎn), 一種是’海水’, 如果A海頂點(diǎn)在B海頂點(diǎn)的周圍8個(gè)格子內(nèi), 那兩個(gè)海頂點(diǎn)就算連通的.

另一個(gè)是’陸地’, 只有A在B的上下左右四個(gè)方格內(nèi), 兩個(gè)陸地才是連通的.

地圖外的方格我們?nèi)恳暈楹#?與地圖外的海連通的海都視為外海, 可以發(fā)現(xiàn), 接觸到了外海的島嶼, 就一定不是其它島嶼的子島。

所以在地圖周圍一圈, 我們?cè)黾右蝗?作為外海, dfs遍歷外海每一個(gè)方格, 若與外海方格相鄰的島嶼未被遍歷過,那么這就是一個(gè)新的島嶼, 再用一個(gè)dfs去遍歷這個(gè)島。

參考代碼

//
// Created by trudbot on 2023/4/9.
//

#include <bits/stdc++.h>
using namespace std;
const int N = 60;
int g[N][N], n, m, res = 0;
bool st[N][N];
int dx[] = {0, 0, 1, -1},
    dy[] = {1, -1, 0, 0};

void dfs_1(int r, int c) {
    st[r][c] = true;
  	//四向連通
    for (int i = 0; i < 4; i ++) {
        int x = dx[i] + r, y = dy[i] + c;
        if (st[x][y] || g[x][y] == 0) continue;
        dfs_1(x, y);
    }
}

void dfs_0(int r, int c) {
    st[r][c] = true;
    //八向連通
    for (int i = -1; i <= 1; i ++)
        for (int j = -1; j <= 1; j ++) {
            int x = r + i, y = c + j;
            if (x < 0 || x > n + 1 || y < 0 || y > m + 1 || st[x][y]) continue;
            if (g[x][y] == 0) dfs_0(x, y);
            else dfs_1(x, y), res ++;
        }
}

int main () {
    int T; cin >> T;
    while (T --) {
        memset(g, 0, sizeof g);
        memset(st, false, sizeof st);
        cin >> n >> m; res = 0;
        for (int i = 1; i <= n; i ++)
            for (int j = 1; j <= m; j ++) {
                char c; cin >> c;
                g[i][j] = c - '0';
            }
        dfs_0(0, 0);//從一個(gè)外海方格開始dfs
        cout << res << endl;
    }
    return 0;
}

試題G: 子串簡(jiǎn)寫

題意描述

程序猿圈子里正在流行一種很新的簡(jiǎn)寫方法:對(duì)于一個(gè)字符串,只保留首尾字符,將首尾字符之間的所有字符用這部分的長(zhǎng)度代替。例如internationalization簡(jiǎn)寫成i18n,Kubernetes (注意連字符不是字符串的一部分)簡(jiǎn)
寫成K8s, Lanqiao 簡(jiǎn)寫成L5o 等。在本題中,我們規(guī)定長(zhǎng)度大于等于K 的字符串都可以采用這種簡(jiǎn)寫方法(長(zhǎng)度小于K 的字符串不配使用這種簡(jiǎn)寫)。

給定一個(gè)字符串S 和兩個(gè)字符 c 1 c_1 c1? c 2 c_2 c2?,請(qǐng)你計(jì)算S 有多少個(gè)以 c 1 c_1 c1? 開頭 c 2 c_2 c2? 結(jié)尾的子串可以采用這種簡(jiǎn)寫?

前綴和

設(shè)p[i]為前i個(gè)字符中 c 1 c_1 c1?字符的個(gè)數(shù), 則對(duì)于下標(biāo)為j c 2 c_2 c2?字符, 以其結(jié)尾且可以簡(jiǎn)寫的子串?dāng)?shù)量即為p[j - k + 1]

參考代碼

//
// Created by trudbot on 2023/4/9.
//

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 5e5 + 10;
ll p[N], res;

int main () {
    int k; cin >> k;
    string s; char a, b; cin >> s >> a >> b;
    for (int i = 1; i <= s.size(); i ++) p[i] = p[i - 1] + (s[i - 1] == a);
    for (int i = k; i <= s.size(); i ++)
        if (s[i - 1] == b) res += p[i - k + 1];
    cout << res << endl;
    return 0;
}

試題H: 整數(shù)刪除

題意描述

給定一個(gè)長(zhǎng)度為N 的整數(shù)數(shù)列: A 1 , A 2 . . . A N A_1,A_2...A_N A1?,A2?...AN?。

你要重復(fù)以下操作K 次:每次選擇數(shù)列中最小的整數(shù)(如果最小值不止一個(gè),選擇最靠前的),將其刪除。并把與它相鄰的整數(shù)加上被刪除的數(shù)值。

輸出K 次操作后的序列。

雙向鏈表 | 最小堆

由于要進(jìn)行大量的刪除操作, 不難想到可以使用鏈表.

而本題需要?jiǎng)討B(tài)的求最小值, 顯然可以使用堆.

每次從堆中取出最小值的下標(biāo), 然后在鏈表中刪除它.

但本題特殊點(diǎn)在于將其刪除。并把與它相鄰的整數(shù)加上被刪除的數(shù)值, 所以會(huì)導(dǎo)致還在堆中的元素的權(quán)的變化.

我們可以注意到, 每次刪除操作只會(huì)讓一些元素變大, 而不會(huì)讓元素變小. 也就是, 可能會(huì)讓原本的最小值變成不是最小值.

因此我們?nèi)〕龆阎械淖钚≈禃r(shí), 需要將此元素的排序權(quán)和實(shí)際的值進(jìn)行對(duì)比, 如果實(shí)際的值變大了, 則當(dāng)前元素并不一定是最小值, 需要重新放回堆中.

參考代碼

每次刪除操作最多會(huì)讓兩個(gè)元素的值變化, 因此從堆中取出的次數(shù)是k的線性, 時(shí)間復(fù)雜度為 O ( n + k ) log ? n O(n + k) \log n O(n+k)logn

//
// Created by trudbot on 2023/4/9.
//

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 5e5 + 10;
ll v[N], l[N], r[N];

void del(int x) {
    r[l[x]] = r[x], l[r[x]] = l[x];
    v[l[x]] += v[x], v[r[x]] += v[x];
}

int main () {
    int n, k; cin >> n >> k;
    r[0] = 1, l[n + 1] = n;
    priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> h;
    for (int i = 1; i <= n; i ++)
        cin >> v[i], l[i] = i - 1, r[i] = i + 1, h.push({v[i], i});
    while (k --) {
        auto p = h.top(); h.pop();
        if (p.first != v[p.second]) h.push({v[p.second], p.second}), k ++;
        else del(p.second);
    }
    int head = r[0];
    while (head != n + 1) {
        cout << v[head]<< " ";
        head = r[head];
    }
    return 0;
}

試題I: 景區(qū)導(dǎo)游

題意描述

某景區(qū)一共有N 個(gè)景點(diǎn),編號(hào)1 到N。景點(diǎn)之間共有N ? 1 條雙向的擺渡車線路相連,形成一棵樹狀結(jié)構(gòu)。在景點(diǎn)之間往返只能通過這些擺渡車進(jìn)行,需要花費(fèi)一定的時(shí)間。

小明是這個(gè)景區(qū)的資深導(dǎo)游,他每天都要按固定順序帶客人游覽其中K 個(gè)景點(diǎn):A1; A2; : : : ; AK。今天由于時(shí)間原因,小明決定跳過其中一個(gè)景點(diǎn),只帶游客按順序游覽其中K ? 1 個(gè)景點(diǎn)。具體來說,如果小明選擇跳過Ai,那么他會(huì)按順序帶游客游覽 A 1 , A 2 . . . A i ? 1 , A i + 1 , A K A_1,A_2... A_{i?1},A_{i+1},A_K A1?,A2?...Ai?1?,Ai+1?,AK? (1 ≤ i ≤ K)。請(qǐng)你對(duì)任意一個(gè)Ai,計(jì)算如果跳過這個(gè)景點(diǎn),小明需要花費(fèi)多少時(shí)間在景點(diǎn)之間的擺渡車上?

帶權(quán)LCA

要確定的一點(diǎn)是, 由于題中的圖是一棵樹, 所以對(duì)于任意兩個(gè)頂點(diǎn), 它們的最短路徑就是它們的簡(jiǎn)單路徑。

求樹中兩個(gè)結(jié)點(diǎn)的最短路徑, 可以想到LCA。

設(shè) d i s t [ u ] dist[u] dist[u]為u頂點(diǎn)到根結(jié)點(diǎn)的距離, 那么u和v的距離即為 d i s t [ u ] + d i s t [ v ] ? 2 ? d i s t [ l c a ( u , v ) ] dist[u] + dist[v] - 2 * dist[lca(u, v)] dist[u]+dist[v]?2?dist[lca(u,v)].

因此本題就是一道LCA的模板題, 使用倍增或者tarjan都是可以的, 具體的算法知識(shí)請(qǐng)自行去學(xué)習(xí)。

距離可能會(huì)爆int, 因此建議是所有整型都用long long, 避免麻煩。

參考代碼

//
// Created by trudbot on 2023/4/10.
//
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
using ll = long long;
vector<pair<int, int>> g[N];
ll dep[N], f[N][30], dist[N];

void dfs(int u, int fa, ll d) {
    dep[u] = dep[fa] + 1, dist[u] = d, f[u][0] = fa;
    for (int i = 1; (1 << i) <= dep[u]; i ++) f[u][i] = f[f[u][i - 1]][i - 1];
    for (auto &p : g[u]) {
        if (p.first == fa) continue;
        dfs(p.first, u, d + p.second);
    }
}

int lca(int a, int b) {
    if (dep[a] < dep[b]) swap(a, b);
    for (int i = 20; i >= 0; i --) {
        if (dep[f[a][i]] >= dep[b]) a = f[a][i];
        if (a == b) return a;
    }
    for (int i = 20; i >= 0; i --) {
        if (f[a][i] != f[b][i]) a = f[a][i], b = f[b][i];
    }
    return f[a][0];
}

ll get(int a, int b) {
    return dist[a] + dist[b] - 2 * dist[lca(a, b)];
}

int main () {
    int n, k; cin >> n >> k;
    for (int i = 1; i < n; i ++) {
        int u, v, t; cin >> u >> v >> t;
        g[u].push_back({v, t}), g[v].push_back({u, t});
    }
    vector<int> a(k);
    for (auto &x : a) cin >> x;
    dfs(1, 0, 0);
    ll sum = 0;
    for (int i = 1; i < k; i ++) sum += get(a[i - 1], a[i]);
    for (int i = 0; i < k; i ++) {
        ll ans = sum;
        if (i != 0) ans -= get(a[i], a[i - 1]);
        if (i != k - 1) ans -= get(a[i], a[i + 1]);
        if (i != 0 && i != k - 1) ans += get(a[i - 1], a[i + 1]);
        cout << ans << " ";
    }
    return 0;
}

試題J: 砍樹

題意描述

給定一棵由n 個(gè)結(jié)點(diǎn)組成的樹以及m 個(gè)不重復(fù)的無序數(shù)對(duì) ( a 1 , b 1 ) , ( a 2 , b 2 ) , . . . , ( a m , b m ) (a_1,b_1), (a_2,b_2),...,(a_m,b_m) (a1?,b1?),(a2?,b2?),...,(am?,bm?),其中 a i a_i ai? 互不相同, b i b_i bi? 互不相同, a i ≠ b j a_i \neq b_j ai?=bj?(1 ≤ i, j ≤ m)。
小明想知道是否能夠選擇一條樹上的邊砍斷,使得對(duì)于每個(gè) ( a i , b i ) (a_i,b_i) (ai?,bi?) 滿足 a i a_i ai? b i b_i bi? 不連通,如果可以則輸出應(yīng)該斷掉的邊的編號(hào)(編號(hào)按輸入順序從1 開始),否則輸出-1。

樹上差分

同上題我們知道, 樹中兩個(gè)結(jié)點(diǎn)的簡(jiǎn)單路徑是唯一的。

因此如果我們能找到一條邊, 每組數(shù)對(duì)的兩個(gè)結(jié)點(diǎn)的簡(jiǎn)單路徑都要經(jīng)過這條邊, 那么就可以滿足題意。

這時(shí)我們可以很簡(jiǎn)單的想到思路, 對(duì)于數(shù)對(duì) ( a , b ) (a, b) (a,b), 我們遍歷a到b路徑上的每一條邊, 讓其權(quán)值加一。

最后若存在權(quán)值為m的邊, 那么就滿足題意。

但這樣做時(shí)間復(fù)雜度顯然最壞是 O ( n m ) O(nm) O(nm), 不達(dá)標(biāo)。

這時(shí)候我們可以用到樹上差分優(yōu)化這一過程, 同理這里不會(huì)贅述它是什么, 請(qǐng)自行去學(xué)習(xí)相關(guān)知識(shí)。文章來源地址http://www.zghlxwxcb.cn/news/detail-439738.html

參考代碼

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = 18;
vector<pair<int, int>> g[N];
int dep[N], f[N][20], cnt[N], w[N];

void init(int u, int fa) {
  dep[u] = dep[fa] + 1, f[u][0] = fa;
  for (int i = 1; (1 << i) <= dep[u]; i ++) f[u][i] = f[f[u][i - 1]][i - 1];
  for (auto &e : g[u]) {
    if (e.first != fa) init(e.first, u), w[e.first] = e.second;
  }
}

int lca(int a, int b) {
  if (dep[a] < dep[b]) swap(a, b);
  for (int i = M; i >= 0; i --) {
    if (dep[f[a][i]] >= dep[b]) a = f[a][i];
    if (a == b) return a;
  }
  for (int i = M; i >= 0; i --) {
    if (f[a][i] != f[b][i]) a = f[a][i], b = f[b][i];
  }
  return f[a][0];
}

void add(int a, int b) {
  int LCA = lca(a, b);
  cnt[a] ++, cnt[b] ++, cnt[LCA] -= 2;
}

void dfs(int u, int fa) {
  for (auto &e : g[u]) {
    if (e.first != fa) 
      dfs(e.first, u), cnt[u] += cnt[e.first];
  }
}

int main () {
  int n, m; cin >> n >> m;
  for (int i = 1; i < n; i ++) {
    int a, b; cin >> a >> b;
    g[a].push_back({b, i}), g[b].push_back({a, i});
  }
  init(1, 0);
  for (int i = 0; i < m; i ++) {
    int a, b; cin >> a >> b;
    add(a, b);
  }
  dfs(1, 0);
  int res = -1;
  for (int i = 1; i <= n; i ++) 
    if (cnt[i] == m && (w[i] > res)) res = w[i];
  cout << res << endl;
  return 0;
}

到了這里,關(guān)于2023第十四屆藍(lán)橋杯C/C++B組省賽題解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 第十四屆藍(lán)橋杯大賽青少年省賽C++組試題真題 2023年5月

    第十四屆藍(lán)橋杯大賽青少年省賽C++組試題真題 2023年5月

    一、選擇題 第 1 題 單選題 C++中,bool類型的變量占用字節(jié)數(shù)為 ( )。 A. 1 B. 2 C. 3 D. 4 第 2 題 單選題 以下關(guān)于C++結(jié)構(gòu)體的說法,正確的是 ( )。 A. 結(jié)構(gòu)體中只能包含成員變量,不能包含成員函數(shù) B. 結(jié)構(gòu)體不能從另一個(gè)結(jié)構(gòu)體繼承 C. 結(jié)構(gòu)體里面可以包含靜態(tài)成員變量 D. 結(jié)構(gòu)體里

    2024年02月15日
    瀏覽(42)
  • 第十四屆藍(lán)橋杯C/C++_大學(xué)B組省賽真題

    【考生須知】 考試開始后,選手首先下載題目,并使用考場(chǎng)現(xiàn)場(chǎng)公布的解壓密碼解壓試題。 考試時(shí)間為 4 小時(shí)??荚嚻陂g選手可瀏覽自己已經(jīng)提交的答案,被瀏覽的答案允許拷貝。時(shí)間截止后,將無法繼續(xù)提交或?yàn)g覽答案。 對(duì)同一題目,選手可多次提交答案,以最后一次提

    2023年04月11日
    瀏覽(24)
  • 2023年第十四屆藍(lán)橋杯大賽python組省賽真題(已更新完)

    本篇更新藍(lán)橋杯省賽真題的后5道。 6.試題 F: 公因數(shù)匹配 時(shí)間限制: 10.0s 內(nèi)存限制: 512.0MB 本題總分:15 分 【問題描述】 給定 n 個(gè)正整數(shù) Ai,請(qǐng)找出兩個(gè)數(shù) i, j 使得 i j 且 Ai 和 Aj 存在大于 1 的 公因數(shù)。 如果存在多組 i, j,請(qǐng)輸出 i 最小的那組。如果仍然存在多組 i, j,請(qǐng)輸出

    2024年02月06日
    瀏覽(35)
  • 第十四屆藍(lán)橋杯省賽C++ B組(個(gè)人經(jīng)歷 + 題解)

    第十四屆藍(lán)橋杯省賽C++ B組(個(gè)人經(jīng)歷 + 題解)

    這是我第一次參加藍(lán)橋杯的省賽,雖然沒什么參賽經(jīng)驗(yàn),但是自己做了很多前幾屆藍(lán)橋杯的題,不得不說,這一屆藍(lán)橋杯省賽的難度相較于之前而言還是比較大的。之前很流行藍(lán)橋杯就是暴力杯的說法,但是隨著參賽人數(shù)的增多,比賽認(rèn)可度的提升,比賽題目的質(zhì)量也明顯越

    2024年02月03日
    瀏覽(36)
  • 第十四屆藍(lán)橋杯省賽c/c++大學(xué)B組題解

    第十四屆藍(lán)橋杯省賽c/c++大學(xué)B組題解

    個(gè)人答案,有錯(cuò)漏感謝指正哈 本題總分:5 分 【問題描述】 ??小藍(lán)現(xiàn)在有一個(gè)長(zhǎng)度為 100 的數(shù)組,數(shù)組中的每個(gè)元素的值都在 0 到 9 的范圍之內(nèi)。數(shù)組中的元素從左至右如下所示: 5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3

    2023年04月12日
    瀏覽(24)
  • 藍(lán)橋杯第十四屆省賽完整題解 C/C++ B組

    藍(lán)橋杯第十四屆省賽完整題解 C/C++ B組

    沒有測(cè)評(píng),不知道對(duì)不對(duì),僅僅過樣例而已 本題總分:5 分 【問題描述】 小藍(lán)現(xiàn)在有一個(gè)長(zhǎng)度為 100 的數(shù)組,數(shù)組中的每個(gè)元素的值都在 0 到 9 的 范圍之內(nèi)。數(shù)組中的元素從左至右如下所示: 5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9

    2023年04月13日
    瀏覽(95)
  • 第十四屆藍(lán)橋杯大賽軟件賽省賽 Java 大學(xué) B 組題解

    找規(guī)律,可以先手動(dòng)模擬幾次,會(huì)發(fā)現(xiàn)?隨著n越大,零也越多,當(dāng)n為40的時(shí)候剛好有9個(gè)0 所以到40項(xiàng)以后的末尾9個(gè)階乘的和一定是不變的,可以用手算,也可以寫程序 答案是,901327897 代碼: Java中有十進(jìn)制轉(zhuǎn)化為二進(jìn)制,十六進(jìn)制,八進(jìn)制的方法,暴力枚舉一下即可。(因?yàn)?/p>

    2024年02月02日
    瀏覽(30)
  • 藍(lán)橋杯2023年第十四屆省賽真題-平方差--題解

    時(shí)間限制: 3s?內(nèi)存限制: 320MB?提交: 2379 解決: 469 給定 L, R,問 L ≤ x ≤ R 中有多少個(gè)數(shù) x 滿足存在整數(shù) y,z 使得 x = y2?? z2。 輸入一行包含兩個(gè)整數(shù) L, R,用一個(gè)空格分隔。 輸出一行包含一個(gè)整數(shù)滿足題目給定條件的 x 的數(shù)量。 復(fù)制 復(fù)制 1 = 1^2?? 0^2 ; 3 = 2^2 ? 1^2 ; 4 =

    2024年02月07日
    瀏覽(28)
  • 第十四屆藍(lán)橋杯大賽軟件賽省賽-試題 B---01 串的熵 解題思路+完整代碼

    歡迎訪問個(gè)人網(wǎng)站來查看此文章:http://www.ghost-him.com/posts/db23c395/ 對(duì)于一個(gè)長(zhǎng)度為 n 的 01 串 S = x 1 x 2 x 3 . . . x n S = x_{1} x_{2} x_{3} ... x_{n} S = x 1 ? x 2 ? x 3 ? ... x n ? ,香農(nóng)信息熵的定義為 H ( S ) = ? ∑ 1 n p ( x i ) l o g 2 ( p ( x i ) ) H(S ) = ? {textstyle sum_{1}^{n}} p(x_{i})log_{2} (p

    2023年04月10日
    瀏覽(32)
  • 藍(lán)橋杯2023年第十四屆省賽真題-買瓜--C語言題解

    目錄 藍(lán)橋杯2023年第十四屆省賽真題-買瓜 題目描述 輸入格式 輸出格式 樣例輸入 樣例輸出 提示 【思路解析】 【代碼實(shí)現(xiàn)】 時(shí)間限制: 3s?內(nèi)存限制: 320MB?提交: 796 解決: 69 小藍(lán)正在一個(gè)瓜攤上買瓜。瓜攤上共有 n 個(gè)瓜,每個(gè)瓜的重量為 Ai?。 小藍(lán)刀功了得,他可以把任何瓜

    2024年02月07日
    瀏覽(50)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包