2024牛客多校第10場

Aderose_yr發表於2024-08-20

10

B std::pair (B)

模擬題,沒什麼難度,就是有點噁心。題解提到的二叉樹做法賽時也想過,但寫著不太順手就放棄了,轉而寫了個類似括號匹配的解法。

    for(int i = 1; i <= n; i++) {
        string s;
        cin >> c[i] >> s;
        mp[s] = i;
    }
    while(q--) {
        string s0, s;
        cin >> s0;
        bool flag = 1;
        for(int i = 0; i < s0.size(); i++) {
            if(s0[i] == '.') {
                s = s0.substr(0, i);
                flag = 0;
                break;
            }
        }
        if(flag) {
            s0 += ";"; // 字串後面還有分號。。。
            cout << c[mp[s0]] << endl;
            continue;
        }
        s += ";";
        int x = mp[s], j = 0;
        for(int i = 0; i < s0.size(); i++) {
            if(s0[i] == '.') { // 相當於需要查詢的層數
                if(s0[i + 1] == 'f') {
                    j += 5; // pair向裡跳一層到first
                }
                else {
                    j += 5;
                    int stk = 0; // 括號匹配
                    for(; j < c[x].size(); j++) {
                        if(c[x][j] == '<') stk++;
                        else if(c[x][j] == '>') stk--;
                        if(stk == 0 && c[x][j] == ',') break;
                    }
                    j++;
                }
            }
        }
        int stk = 0;
        for(; j < c[x].size(); j++) {
            if(c[x][j] == '<') stk++;
            else if(c[x][j] == '>') stk--;
            cout << c[x][j];
            if(c[x][j] == 't' || c[x][j] == 'e' || c[x][j] == '>') {
                if(stk == 0) break;
            }
        }
        cout << endl;
    }

K Doremy's IQ 2 (K)

假設所有題目的難度滿足 \(a\leq 0\). 若最終智商降為 \(m\),最優情況下所有 \(a_i > m\)(或許還有一部分 \(a_i = m\))都應作為 \(d=x\)-type,其餘題目則用於拉低智商,不計入答案中;\(a\geq 0\) 時與之相似。如此可以 \(O(1)\) 檢驗任意一個 \(m\) 取值的合法性,考慮二分答案求解。對於 \(a\) 有正有負的情況,為使答案更優,Doremy智商的單調性最多發生一次變化。可從 \(1\)\(n\) 列舉智商第一次遞增/遞減到的位置,然後二分求其反方向可能存在的最優解。複雜度 \(n\log n\).

    int x = 0, y = 0, z = 0;
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        if(a[i] < 0) x++;
        else if(a[i] == 0) y++;
        else z++;
    }
    int ans = 0;
    for(int i = 1; i <= x; i++) {
        if(i - 1 < -a[i]) continue;
        int res = 0, l = x + y + 1, r = n;
        while(l <= r) {
            int mid = (l + r) / 2;
            if(a[mid] - a[i] <= n - mid) {
                res = mid - x - y;
                l = mid + 1;
            } else r = mid - 1;
        }
        ans = max(ans, res + x - i + 1);
    }
    for(int i = x + y + 1; i <= n; i++) {
        if(n - i < a[i]) continue;
        int res = 0, l = 1, r = x;
        while(l <= r) {
            int mid = (l + r) / 2;
            if(a[i] - a[mid] <= mid - 1) {
                res = x - mid + 1;
                r = mid - 1;
            } else l = mid + 1;
        }
        ans = max(ans, res + i - x - y);
    }
    printf("%d\n", ans + y);

L Tada! (L)

由於 \(n\leq 5\),每次操作可以到達的狀態最多隻有 \(({5\choose2} + 5)\times 2 = 30\) 種,將每條資訊的 \(s\) 作為起始位置,bfs計算其到達各個狀態的最小操作次數,\(t\) 次能夠到達的所有合法狀態取交集即為答案。開始我們認為bfs求出的“最短路”滿足 \(d_i\leq t\) 時,即可透過擴大/縮小操作區間湊成 \(t\) 次操作,後來發現遺漏了兩個特判:\(n = 1\) 時操作區間無法改變,應嚴格滿足 \(d_i = t\);起點位置需要至少 \(2\) 次操作才能恢復原來狀態,因此 \(t = 1\) 時起點位置不合法。特判後即可透過,時間複雜度 \(30mn\cdot 10^n\).

程式碼不是我寫的,也不太想再寫一遍,多少有點噁心

相關文章