07_04_暑期個人賽1

lulaalu發表於2024-07-05

C. Canine poetry

時間:2024-07-05

原題:Good Bye 2020 C. Canine poetry

題意

對於一個字串 \(s\) ,可以對任一字元變為 \(*\) 號,使所有子串不為迴文串,即可將 \(babba\) 變為 \(ba*ba\) 使字串內不存在迴文串

資料範圍: \(|s|\le 1e5\)

思路

對於某迴文字串,如果是長度為奇數,那麼中心的三個字元組成的子串一定是字串,偶數同理

那麼將所有的長度為2和3的迴文串進行處理就能達到效果

程式碼

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
#define int long long

int _, n;
vector<bool>vis;
void solve() {
    string s;
    cin >> s;
    int len = s.length();
    vis.assign(len, false);

    int ans = 0;
    for (int i = 1; i < s.length(); i++) {
        // 長度為2的迴文串,如果沒被換過,換後面的字元
        if (s[i] == s[i - 1] && !vis[i - 1]) {
            vis[i] = true;
            ans++;
        }
        // 長度為3的迴文串,同理換第一個
        else if (i - 2 >= 0 && s[i] == s[i - 2] && !vis[i - 2]) {
            vis[i] = true;
            ans++;
        }
    }
    cout << ans << endl;
}
signed main() {
    cin >> _;
    while (_--)
        solve();
    return 0;
}

C. Ehab and Path-etic MEXs

時間:2024-07-05

原題:Codeforces Round 628 (Div. 2) C. Ehab and Path-etic MEXs

題意

有一顆 \(n\) 個結點的樹,對每條邊編號,屬於 \([0,n-2]\) ,要求所有對節點對 \((u,v)\) ,其 \(MEX(u,v)\) 的最大值最小

\(MEX(u,v)\) 表示從 \(u\)\(v\) 的唯一簡單路徑上沒出現過的最小編號

理解: 有點繞,就是說,有從 \(u\)\(v\) 假如經過了邊1,2,4那麼最小的未出現的數就是0,則 \(MEX(u,v)=0\)

\(Ans=max(MEX(u,v))\) ,求 \(Ans_{min}\)

思路

首先假定是最簡單的情況,也就是一條鏈,那麼簡單看一下所有的可能性,可知 \(Ans=n-1\)

所以對於單鏈,隨機存放即可

接下來,如果多了一條鏈,那麼可以觀察度大於等於3的點

對於這樣的點,無論哪種 \((u,v)\) 的搭配,對於這個點至少有一條邊不被覆蓋

即只要將0,1,2這最小的三個編號分配在三條分路上,其他編號隨意分配,就能實現 \(Ans=2\)

程式碼

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

#define int long long
#define rep(i,j,k) for(i=(j);i<(k);i++)
typedef pair<int, int> pii;
const int N = 1e5 + 10;

int n, ii;

vector<vector<int>>g;
int u[N], v[N];
void solve() {
    cin >> n;
    g.assign(n + 1, vector<int>(0));

    rep(ii, 0, n - 1) {
        cin >> u[ii] >> v[ii];
        g[u[ii]].emplace_back(v[ii]);
        g[v[ii]].emplace_back(u[ii]);
    }
    // 如果有大於等於3的度,以儲存兩個頂點的形式儲存每條邊,012對應共三條
    pii p[3];
    int i;
    for (i = 0; i < g.size(); i++) {
        vector<int> vv = g[i];
        if (vv.size() >= 3) {
            for (int j = 0; j < 3; j++) {
                p[j].first = i;
                p[j].second = vv[j];
            }
            break;
        }
    }
    // 如果沒有大於等於3的度,隨意輸出
    if (i == g.size()) {
        rep(ii, 0, n - 1) {
            cout << ii << endl;
        }
        return;
    }

    
    int ans = 0;
    int index = 3;
    for (int i = 0; i < n - 1; i++) {
        int j;
        for (j = 0; j < 3; j++) {
            int f = p[j].first, s = p[j].second;
            // 如果是012所在的邊,輸出012,否則輸出index
            if ((u[i] == f && v[i] == s) || (u[i] == s && v[i] == f)) {
                cout << ans << endl;
                ans++;
                break;
            }
        }
        if (j == 3) {
            cout << index++ << endl;
        }
    }
}
signed main() {
    solve();
    return 0;
}

相關文章