1. 程式人生 > 實用技巧 >Codeforce:Good Bye 2020 個人題解

Codeforce:Good Bye 2020 個人題解

題面連結:Here

程式碼提交:Here

年終彩蛋

1466A. Bovine Dilemma

題意是:給定一個固定點(0,1),然後給定n個在x軸的點,求面積不同的三角形個數

簡單思考一下就容易發現這個是一個高相等的三角形,只需要去比較底邊的長度不同的有多少個即可。

//AC程式碼
void solve() {
    cin >> n;
    vector<int> v(n);
    for (int i = 0; i < n; ++i)
        cin >> v[i];
    if (n == 1) {
        cout << 0 << endl;
        return;
    }
    set<int> s;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            if (i != j)
                s.insert(v[j] - v[i]);
    //由於直接暴力找的答案是正解的兩倍(會存入等大小的負值),所以要除2
    cout << s.size() / 2 << endl;
}

進階挑戰:Try to solve it for \(n,x_i≤10^5\).

//待補

1466B. Last minute enhancements

給定\(n\) 個音符的值,當可以為重複出現的值加一時,最終能有多少個不同音符

標記出現過的,如果下次還出現則令其加一再標記

//原提交寫法
void solve() {
    cin >> n;
    vector<int> v(n);
    int cnt = 0, sum = 0;
    int book[2 * (n + 1)] = {0};
    set<int> s;
    for (int i = 0; i < n; ++i) {
        cin >> v[i];
        if (book[v[i]])
            v[i]++;
        s.insert(v[i]);
        book[v[i]]++;
    }
    if (n == 1) {
        cout << 1 << endl;
        return;
    }
    cout << s.size() << endl;
}
//寫法優化
void solve() {
    ll n, x;
    cin >> n;
    set<ll> s;
    for (int i = 0; i < n; ++i) {
        cin >> x;
        if (s.count(x))
            x++;
        s.insert(x);
    }
    cout << s.size() << endl;
}
//多利用STL函式幫助解決問題

進階挑戰:對於給定的 \(k_i\),如果我們可以將音符 \(x_i\) 增加 [0,\(k_i\)

]中的任何整數,可以解決嗎?

//待補

1466C. Canine poetry

如果存在一個長度大於3的迴文,則存在一個長度為2或3的迴文。此觀察結果使我們可以簡化擦除所有長度為2或3的迴文的任務。 每個字元最多將被替換一次。

從現在開始,有幾種可能的解決方案。 最簡單的方法是從左到右遍歷一個單詞。 當我們遇到以當前位置結束的迴文(長度為2或3),並且由未標記的元素組成時,我們會貪婪地將此字元標記為要替換的字元。 標記字元的數目就是答案,因為事實證明,通過僅替換標記位置上的字母,我們可以獲得有效的無迴文序列。 複雜度為O(n)。

當然這道題也可以用DP做,但更復雜:時間複雜度\(O(n*26^2)\)

char s[N];
bool vis[N];
void solve() {
    cin >> (s + 1);
    n = strlen(s + 1);
    for (int i = 1; i <= n; i += 1)
        vis[i] = 0;
    int ans = 0;
    for (int i = 1; i <= n; i += 1) {
        if (i >= 2 and s[i] == s[i - 1] and not vis[i - 1]) {
            vis[i] = 1;
            ans += 1;
        }
        if (i >= 3 and s[i] == s[i - 2] and not vis[i - 2] and not vis[i]) {
            vis[i] = 1;
            ans += 1;
        }
    }
    cout << ans << "\n";
}

進階挑戰:如果字母可以更改,並且每次更改後都需要計算結果怎麼辦?

1466D. 13th Labour of Heracles

樹構造,寫一下入度和出度

ll w[N];
int d[N];
void solve() {
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> w[i], d[i] = 0;

    for (int i = 1, u, v; i < n; i++) {
        cin >> u >> v;
        d[u] += 1, d[v] += 1;
    }

    ll ans = 0;
    vector<ll> v;
    for (int i = 1; i <= n; i++) {
        ans += w[i];
        for (int j = 1; j < d[i]; j++)
            v.push_back(w[i]);
    }
    sort(v.begin(), v.end(), greater<ll>());
    cout << ans << " ";
    for (ll x : v)
        cout << (ans += x) << " ";
    cout << endl;
}

1466E. Apollo versus Pan

//待補

1466F. Euclid's nightmare

//待補