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;
}

D

计算几何……

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;
}

F

二分图相关……

原文地址:https://www.cnblogs.com/handwer/p/15403849.html