牛客周賽 Round 67 A~F

AdviseDY發表於2024-11-18

牛客周賽 Round 67 A~F題解

目錄
  • 牛客周賽 Round 67 A~F題解
    • Preface
      • 所有程式碼前面的火車頭
    • Problem A.排序危機
    • Problem B.小歪商店故事:卷
    • Problem C.小苯的計算式
    • Problem D.K
    • Problem E.小苯的區間選數
    • Problem F.小Z的樹遷移
    • PostScript

Preface

好久沒v過牛客周賽了,但估計這場強度不高是特例吧,感覺AK還是不太難的,最後一題也還好,想到了做起來也不太難,還是多v挑戰賽吧。

所有程式碼前面的火車頭

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <unordered_map>
#include <iomanip>
#define endl '\n'
#define int long long
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define rep2(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
template<typename T>
void cc(vector<T> tem) { for (auto x : tem) cout << x << ' '; cout << endl; }
void cc(int a) { cout << a << endl; }
void cc(int a, int b) { cout << a << ' ' << b << endl; }
void cc(int a, int b, int c) { cout << a << ' ' << b << ' ' << c << endl; }
void fileRead() {
#ifdef LOCALL
    freopen("D:\\AADVISE\\cppvscode\\CODE\\in.txt", "r", stdin);
    freopen("D:\\AADVISE\\cppvscode\\CODE\\out.txt", "w", stdout);
#endif
}
void kuaidu() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); }
inline int max(int a, int b) { if (a < b) return b; return a; }
inline int min(int a, int b) { if (a < b) return a; return b; }
void cmax(int& a, const int b) { if (b > a) a = b; }
void cmin(int& a, const int b) { if (b < a) a = b; }
using PII = pair<int, int>;
using i128 = __int128;


Problem A.排序危機

只能說這個簽到給我寫複雜了,其實只需要先輸出小寫字母,再輸出數字,最後輸出大寫字母就好了,我卻唐成了結構體排序,複雜度還多了一個\(log\)

//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;

//--------------------------------------------------------------------------------
//struct or namespace:
struct node {
    char x;
    int val;
    int id;
};
node A[N];
//--------------------------------------------------------------------------------

signed main() {
    fileRead();
    kuaidu();
    T = 1;
    //cin >> T;
    while (T--) {
        cin >> n;
        rep(i, 1, n) {
            char a; int b; cin >> a;
            if (a <= '9' and a >= '0') b = 2;
            if (a <= 'z' and a >= 'a') b = 1;
            if (a <= 'Z' and a >= 'A') b = 3;
            A[i] = { a,b,i };
        }
        sort(A + 1, A + n + 1, [&](const node& q1, const node& q2) {
            if (q1.val == q2.val) return q1.id < q2.id;
            return q1.val < q2.val;
            });
        rep(i, 1, n) {
            cout << A[i].x;
        }

    }
    return 0;
}
/*


*/

Problem B.小歪商店故事:卷

按照題意模擬就好了,直接計算\(b*c/d\)就好了,要注意整除的情況。

//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;

//--------------------------------------------------------------------------------
//struct or namespace:

//--------------------------------------------------------------------------------

signed main() {
    fileRead();
    kuaidu();
    T = 1;
    cin >> T;
    while (T--) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        int aa = b * c / d;
        if ((b * c) % d == 0) aa -= 1;
        cout << a - aa << ' ';

    }
    return 0;
}
/*


*/

Problem C.小苯的計算式

\(C\)的範圍比較小,一眼直接暴力列舉\(A\)即可,\(B\)也就能直接\(C-A\)出來了。

//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;

//--------------------------------------------------------------------------------
//struct or namespace:

//--------------------------------------------------------------------------------

signed main() {
    fileRead();
    kuaidu();
    T = 1;
    // cin >> T;
    while (T--) {
        int c; cin >> n >> c;
        n -= to_string(c).size() + 2;
        int ans = 0;
        rep(i, 0, c) {
            string a = to_string(i), b = to_string(c - i);
            if (a.size() + b.size() == n) ans++;
        }
        cc(ans);

    }
    return 0;
}
/*


*/

Problem D.K

感覺總算有點不是給小白做的題了,區域賽簽到題水平?

\(k==n\)的時候直接一直輸出\(1\)就好了。

隨便手玩一下,會發現可以直接構造1,2,1,2,這種長度是\(n\)的序列我們可以造出來\(k=n-1\)的情況來,如果\(k<n-1\)的情況,我們就可以直接讓後面一直迴圈一個數字,變成1,2,1,2,2, 2, 2,這種就能夠滿足了,程式碼中間只需要注意是讓\(1\)迴圈還是\(2\)迴圈就好。

順便要注意會有\(k>n\)的情況,要特判\(NO\),因為這個\(WA\)了一發。TAT

//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;

//--------------------------------------------------------------------------------
//struct or namespace:

//--------------------------------------------------------------------------------

signed main() {
    fileRead();
    kuaidu();
    T = 1;
    //cin >> T;
    while (T--) {
        int k; cin >> n >> k;
        if (k > n) {
            cout << "NO" << endl;
            continue;
        }
        cout << "YES" << endl;
        
        if (n == k) {
            rep(i, 1, n) cout << 1 << " ";
            continue;
        }
        if (n - 1 == k) {
            for (int i = 1; i <= n; i += 2) {
                cout << "1 2 ";
            }
            continue;
        }
        if (k % 2 == 0) {
            for (int i = 1; i <= k / 2; i++) {
                cout << "1 2 ";
            }
            cout << 1 << " ";
            for (int i = 1; i <= n - k - 1; i++) {
                cout << 1 << " ";
            }
        }
        else {
            for (int i = 1; i <= (k + 1) / 2; i++) {
                cout << "1 2 ";
            }
            for (int i = 1; i <= n - k - 1; i++) {
                cout << 2 << " ";
            }
        }

    }
    return 0;
}
/*


*/

Problem E.小苯的區間選數

首先應該一眼反應過來\(sum\)就是要在\(l=l_1+l_2\)\(r=r_1+r_2\)之間選擇就好了,竟然一開始沒看出來。。。

之後還是手玩一下會發現,比如\(123,159。\)我們只需要找到兩個數字第一個不相等的地方,使這一個位置是\(r-1\),後面一直變成\(99999\)就好了。如果\(l\)\(r\)的長度不一樣,給\(l\)補上前導\(0\)就好了。

但要注意如果r本身就是\(999\)結尾的情況,我們只需要再計算一下\(sum=\)\(l\)\(r\)的情況就可以解決。

//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;
 
//--------------------------------------------------------------------------------
//struct or namespace:
 
//--------------------------------------------------------------------------------
 
signed main() {
    fileRead();
    kuaidu();
    T = 1;
    cin >> T;
    while (T--) {
        int l1, l2, r1, r2;
        cin >> l1 >> r1 >> l2 >> r2;
        int l = l1 + l2, r = r1 + r2;
        int ans1 = 0, ans2 = 0, ans3 = 0;
        string s1 = to_string(l), s2 = to_string(r);
        for (auto& x : s1) {
            ans1 += x - '0';
        }
        for (auto& x : s2) {
            ans2 += x - '0';
        }
        while (s1.size() != s2.size()) s1 = '0' + s1;
        int len = s1.size();
        int num = 0;
        for (int i = 0; i < len; i++) {
            if (s1[i] == s2[i]) {
                ans3 += s1[i] - '0';
                num = (s1[i] - '0') + num * 10;
                continue;
            }
            ans3 += (s2[i] - '0' - 1);
            ans3 += 9 * (len - 1 - i + 1 - 1);
            break;
        }
        ans1 = max({ ans1,ans2,ans3 });
        cc(ans1);
    }
    return 0;
}
/*
 
 
*/

Problem F.小Z的樹遷移

只能說寫這題腦子有些唐了,竟然預設成這個樹會是一個均攤的樹,算下來發現\(logn\)不到20,直接寫了個暴力\(dp\),只能說腦子太秀逗了。

之後冷靜思考,發現純純暴力啟發式合併就好了。先離線處理詢問。給每一個點開一個並查集,裡面開一個\(map\)\(key\)是層數,\(val\)是存有這個點子樹內每一層的\(pre[i]\)最大值就好了,\(pre[i]\)代表\(i\)點到達根節點之間的距離。計算向下走\(d\)次的答案時便是\(mp[dep[x]+d]-pre[x]\)

關於啟發式合併的複雜度這裡便不再贅述,用的是比較好寫的寫法,複雜度會因為\(map\)多一個\(log\),可以使用樹上啟發式合併,複雜度是會少一個\(log\)的。

時間複雜度是\(O(n*logn*logn)\)

//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;
vector<PII> A[N];
vector<PII> qs[N];
int pre[N], dep[N];
int ans[N];
//--------------------------------------------------------------------------------
//struct or namespace:
namespace DSU {
    const int N = 1e5 + 10;
    struct Info {
        int fa;
        int siz;
        map<int, int> mp;
    };
    Info dsu[N];
    void init(int n) {
        //TO DO 記得初始化
        rep(i, 0, n) {
            dsu[i].fa = i, dsu[i].siz = 1;
        }
    }
    int find(int x) { if (x == dsu[x].fa) return x; return dsu[x].fa = find(dsu[x].fa); }
    void merge(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) return;
        dsu[y].fa = dsu[x].fa;
        if (dsu[x].siz < dsu[y].siz) swap(x, y);
        dsu[y].fa = dsu[x].fa;

        dsu[x].siz += dsu[y].siz;
        for (auto [a, b] : dsu[y].mp) {
            cmax(dsu[x].mp[a], b);
        }
    }
    bool same(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) return 1; return 0;
    }
    int size(int x) { return dsu[find(x)].siz; }
}
using DSU::dsu;
//--------------------------------------------------------------------------------

void dfs(int x, int pa) {
    dep[x] = dep[pa] + 1;

    for (auto [y, val] : A[x]) {
        if (y == pa) continue;
        pre[y] = pre[x] + val;
        dfs(y, x);
    }

    dsu[x].mp[dep[x]] = pre[x];
    for (auto [y, val] : A[x]) {
        if (y == pa) continue;
        DSU::merge(x, y);
    }

    int rt = DSU::find(x);
    for (auto [dis, id] : qs[x]) {
        if (dsu[rt].mp.find(dis + dep[x]) == dsu[rt].mp.end()) ans[id] = -1;
        else ans[id] = dsu[rt].mp[dis + dep[x]] - pre[x];
    }

}

signed main() {
    fileRead();
    kuaidu();
    T = 1;
    //cin >> T;
    while (T--) {
        cin >> n;
        rep(i, 1, n - 1) {
            int a, b, c; cin >> a >> b >> c;
            A[a].push_back({ b,c });
            A[b].push_back({ a,c });
        }
        int q; cin >> q;
        rep(i, 1, q) {
            int x, dep; cin >> x >> dep;
            qs[x].push_back({ dep,i });
        }

        DSU::init(n);
        pre[1] = 0;

        dfs(1, 0);
        rep(i, 1, q) {
            cout << ans[i] << endl;
        }

    }
    return 0;
}
/*


*/

PostScript

最近太擺了,感覺EC-Final肯定鐵了,也不太有訓練的心態了。慢慢康復訓練吧。

相關文章