1. 程式人生 > 其它 >Educational Codeforces Round 2 覆盤

Educational Codeforces Round 2 覆盤

A. Extract Numbers

有一說一這題挺毒的,乍一看是個垃圾模擬其實要處理的東西還蠻多,而且我還決定了要邊讀入邊處理,再加上 Vim 用的還不熟練,寫著寫著就寫急躁了。因此我總共寫了 17 分鐘,換了兩種寫法才過。

一遍 AC。

#錯誤警示:心態很重要,細節也要想清楚。Think twice, code once.

const int MAXN = 1e5 + 10;

char ss[MAXN];
int n;
std::vector<std::string> nums;
std::vector<std::string> oths;

int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> (ss + 1);
    n = (int) strlen(ss + 1);
    std::string s;
    bool num = false;
    bool lz = false;
    bool others = false;
    for (int i = 1; i <= n; ++i) {
        if (ss[i] == ',' || ss[i] == ';') {
            if (s.empty() || !num || others) oths.push_back(s);
            else nums.push_back(s);
            s.clear();
            num = lz = others = false;
        } else {
            s += ss[i];
            if (!isdigit(ss[i]) || others) {
                num = false; others = true; continue;
            }
            if (num == false && others == false && isdigit(ss[i])) {
                num = true; 
                if (ss[i] == '0') lz = true;
                continue;
            }
            if (lz && isdigit(ss[i])) {
                num = false; others = true; continue;
            }
        }
    }
            if (s.empty() || !num || others) oths.push_back(s);
            else nums.push_back(s);
            s.clear();
            num = lz = others = false;
    if (nums.size() != 0) {
        cout << "\"";
        forall (nums, i) {
            cout << nums[i];
            if (i != (int) nums.size() - 1) cout << ',';
        }cout << "\"" << endl;
    } else cout << "-" << endl;
    if (oths.size() != 0) {
        cout << "\"";
        forall (oths, i) {
            cout << oths[i];
            if (i != (int) oths.size() - 1) cout << ',';
        }cout << "\"" << endl;
    } else cout << "-" << endl;
    return 0;
}

B. Queries about less or equal elements

這題也是有非常嚴重的失誤,最開始已經想到了最簡單的做法:離線後排序 B 陣列然後一個指標掃過去,但是不知道為啥還是決定手寫二分,結果光榮寫掛。瞪了一會未果決定換離散化 + 樹狀陣列,然而還是掛在後面幾個點。

又瞪了一會無果,打算隨機改幾個易錯點,正好發現樹狀陣列的最大長度可以達到二倍的 n,遂把陣列開大兩倍不放心又開個 long long,交一遍過了。但實際上是不用開 long long 的。

#錯誤警示:一定要穩紮穩打考慮好所有細節,比如最大資料範圍到底能有多少,特別是 CP 這種爭分奪秒的比賽欲速一定不達。

const int MAXN = 2e5 + 10;

int n, m;
lli aa[MAXN], bb[MAXN];
lli nums[MAXN * 2], cnt;

struct BIT {
    lli ss[MAXN * 2];

    void mod(int x) {
        for (; x <= n + m; x += (x & (-x))) ++ss[x];
    }
    int qry(int x) {
        int r = 0;for (; x; x -= (x & (-x))) r += ss[x];
        return r;
    }
} bt;

int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    rep (i, 1, n) {
        cin >> aa[i]; nums[++cnt] = aa[i];
    }
    rep (i, 1, m) {
        cin >> bb[i]; nums[++cnt] = bb[i];
    }
    std::sort(nums + 1, nums + 1 + cnt);
    cnt = (std::unique(nums + 1, nums + 1 + cnt) - nums - 1);
    // DEBUG(cnt);
    for (int i = 1; i <= n; ++i) {
        aa[i] = (std::lower_bound(nums + 1, nums + 1 + cnt, aa[i]) - nums);
        bt.mod(aa[i]);
        // DEBUG(aa[i]);
    }
    rep (i, 1, m) bb[i] = (std::lower_bound(nums + 1, nums + 1 + cnt, bb[i]) - nums);
    rep (i, 1, m) {
        cout << bt.qry(bb[i]) << ' ';
        // DEBUG(bb[i]);
    } cout << endl;
    return 0;
}

C. Make Palindrome

做法很顯然了,就是修改所有出現奇數次的字元。然而我最開始光考慮到字典序最小的要求,於是把所有奇數次字母都找了一個修改成了 'a',這個肯定是不符合修改次數最小的條件的,交上去就光榮 WA 了。瞪了一會無果,開始隨機手造資料,結果第一發就把自己 hack 掉了,然後才意識到這個修改次數不是最小的,接著才想到正解。

結果交上去第二發還是 WA 了,發現自己只修改了長度為奇數的情況,偶數是一樣的。然後才過掉了這題。

#錯誤警示:槽點太多不知從何說起,一定不要想當然,好好考慮一下貪心策略是不是對的、需不需要分類討論。

const int MAXN = 2e5 + 10;

char ss[MAXN];
int n;
int cnt[27];

int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> (ss + 1); n = (int) strlen(ss + 1);
    for (int i = 1; i <= n; ++i) {
        ++cnt[ss[i] - 'a'];
    }
    if (n & 1) {
        // at most one odd
        
        std::vector<int> odds;
        for (int i = 0; i < 26; ++i) {
            if (cnt[i] & 1) {
                odds.push_back(i);
            }
        }
        std::reverse(ALL(odds));
        for (int i = 0, siz = (int) odds.size(); i < siz / 2; ++i) {
            --cnt[odds[i]]; ++cnt[odds[odds.size() - 1 - i]];
        }
        int fx = 0;
        for (int i = 0; i < 26; ++i) {
            if (cnt[i] & 1) fx = i;
            for (int j = 1; j <= cnt[i] / 2; ++j) {
                cout << (char) (i + 'a');
            }
        } cout << (char) (fx + 'a');
        for (int i = 25; i >= 0; --i) {
            for (int j = 1; j <= cnt[i] / 2; ++j) {
                cout << (char) (i + 'a');
            }
        }
    } else {
        // no odd
        std::vector<int> odds;
        for (int i = 0; i < 26; ++i) {
            if (cnt[i] & 1) {
                odds.push_back(i);
            }
        }
        std::reverse(ALL(odds));
        for (int i = 0, siz = (int) odds.size(); i < siz / 2; ++i) {
            --cnt[odds[i]]; ++cnt[odds[odds.size() - 1 - i]];
        }
        for (int i = 0; i < 26; ++i) {
            for (int j = 1; j <= cnt[i] / 2; ++j) {
                cout << (char) (i + 'a');
            }
        }
        for (int i = 25; i >= 0; --i) {
            for (int j = 1; j <= cnt[i] / 2; ++j) {
                cout << (char) (i + 'a');
            }
        }
    }
    return 0;
}

E. Lomsat gelral

dsu on tree 板子題。後面會寫專題題解。

const int MAXN = 1e5 + 10;

int n, col[MAXN];
std::vector<int> G[MAXN];
int siz[MAXN], heavy[MAXN];

void dfs(int u, int fa) {
    siz[u] = 1;
    for (auto v : G[u]) {
        if (v == fa) continue;
        dfs(v, u);
        siz[u] += siz[v];
        if (siz[v] > siz[heavy[u]]) heavy[u] = v;
    }
}

lli cnt[MAXN], mxcnt, thisans, fson;
lli ans[MAXN];

void get(int u, int fa, int x) {
    cnt[col[u]] += x;
    if (cnt[col[u]] > mxcnt) mxcnt = cnt[col[u]], thisans = col[u];
    else if (cnt[col[u]] == mxcnt) thisans += col[u];
    for (auto v : G[u]) {
        if (v == fa || v == fson) continue;
        get(v, u, x);
    }
}
void dfs2(int u, int fa, bool del) {
    mxcnt = thisans = 0;
    for (int v : G[u]) {
        if (v == fa) continue;
        if (v != heavy[u]) dfs2(v, u, true);
    } if (heavy[u]) dfs2(heavy[u], u, false), fson = heavy[u];
    
    get(u, fa, 1); fson = 0;
    ans[u] = thisans;
    if (del) { get(u, fa, -1); mxcnt = thisans = 0; }
}

int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n;
    rep (i, 1, n) cin >> col[i];
    rep (i, 1, n - 1) {
        int u, v; cin >> u >> v;
        G[u].push_back(v); G[v].push_back(u);
    }
    dfs(1, 0);
    dfs2(1, 0, true);
    rep (i, 1, n) cout << ans[i] << ' ';
    cout << endl;
    return 0;
}