[ABC339] 赛后总结

[ABC339] 赛后总结

A.TLD

STL1min 秒了。

cout << s.substr(s.rfind('.') + 1);

B.Langton's Takahashi

纯模拟

for(int t = 1; t <= k; t ++) {
    if(g[x][y] == 0) {
        g[x][y] ^= 1;
        d = (d + 1) % 4;
        x = dx[d] + x, y = dy[d] + y;
    }
    else {
        g[x][y] ^= 1;
        d = (d + 3) % 4;
        x = dx[d] + x, y = dy[d] + y;
    }
    x = (x + n) % n, y = (y + m) % m;
}

C.Perfect Bus

脑筋急转弯

for(int i = 1; i <= n; i ++) {
    sum += a[i];
    mn = min(mn, sum);
}
cout << sum + (mn < 0 ? -mn : 0) << '\n';

D.Synchronized Players

记忆化寄了,要写 BFS。

queue<qwq> q;
f[a][b][c][d] = 0;
q.push({a, b, c, d});
while(q.size()) {
    auto [a, b, c, d] = q.front();
    q.pop();
    if(st[a][b][c][d]) continue; st[a][b][c][d] = 1;
    for(int i = 0; i < 4; i ++) {
        int aa = a + dx[i], bb = b + dy[i], cc = c + dx[i], dd = d + dy[i];
        if(!check(aa, bb)) aa = a, bb = b;
        if(!check(cc, dd)) cc = c, dd = d;
        if(aa == a && bb == b && cc == c && dd == d) continue;
        f[aa][bb][cc][dd] = min(f[aa][bb][cc][dd], f[a][b][c][d] + 1);
        q.push({aa, bb, cc, dd});
    }
}
int ans = INF;
for(int i = 1; i <= n; i ++)
    for(int j = 1; j <= n; j ++) ans = min(ans, f[i][j][i][j]);

E.Smooth Subsequence

易得

\[f_i = \max_{j < i\wedge a_i - d \le a_j\le a_i + d} f_j + 1 \]

二位偏序,线段树优化即可。

for(int i = 1; i <= n; i ++) {
    f[i] = 1;
    f[i] = max(f[i], query(1, max(1, a[i] - d), min(M, a[i] + d)) + 1);
    update(1, a[i], f[i]);
    ans = max(ans, f[i]);
}

F.Product Equality

可以对 \(a_i\) 进行取模,由于出题人卡不到,滚一遍键盘单模数哈希就可以过。

__int128 a[N], mod = 27478509823912369249;
map<__int128, __int128> h;
void work() {
    cin >> n;
    for(int i = 1; i <= n; i ++) {
        string s;
        cin >> s;
        for(auto c : s) a[i] = a[i] * 10 % mod + (c - '0');
    }
    for(int i = 1; i <= n; i ++) for(int j = 1; j <= n; j ++) h[a[i] * a[j] % mod] ++;
    int ans = 0;
    for(int i = 1; i <= n; i ++) ans += h[a[i]];
    cout << ans << '\n';
    return ;
}

G.Smaller Sum

主席树模板了吧算是,直接存储值域的历史版本就好了。

高贵的 \(O(q\log n + n\log n)\)

int n, a[N], disc[N], tot, q;
int find(int x) {
    return lower_bound(disc + 1, disc + tot + 1, x) - disc;
}
int ls[M], rs[M], idx, root[N], dat[M];
int update(int q, int l, int r, int x, int v) {
    int p = ++ idx, mid = l + r >> 1;
    ls[p] = ls[q], rs[p] = rs[q], dat[p] = dat[q];
    if(l == r) return dat[p] = v, p;
    if(x <= mid) ls[p] = update(ls[q], l, mid, x, v);
    else rs[p] = update(rs[q], mid + 1, r, x, v);
    dat[p] = dat[ls[p]] + dat[rs[p]];
    return p;
}
int query(int u, int l, int r, int ql, int qr) {
    int mid = l + r >> 1;
    if(ql <= l && qr >= r) return dat[u];
    int tmp = 0;
    if(ql <= mid) tmp = query(ls[u], l, mid, ql, qr);
    if(qr > mid) tmp += query(rs[u], mid + 1, r, ql, qr);
    return tmp;
}
vector<int> d[N];
void work() {
    cin >> n;
    for(int i = 1; i <= n; i ++) cin >> a[i], disc[++ tot] = a[i];
    sort(disc + 1, disc + tot + 1);
    tot = unique(disc + 1, disc + tot + 1) - disc - 1;
    for(int i = 1; i <= n; i ++)
        d[find(a[i])].push_back(i);
    for(int i = 1; i <= tot; i ++) {
        root[i] = root[i - 1];
        for(auto x : d[i])
            root[i] = update(root[i], 1, n, x, a[x]);
    }
    cin >> q;
    for(int i = 1, lst = 0, l, r, x; i <= q; i ++) {
        cin >> l >> r >> x;
        l ^= lst, r ^= lst, x ^= lst;
        if(x < disc[1]) {
            cout << (lst = 0) << '\n';
            continue;
        }
        cout << (lst = query(root[upper_bound(disc + 1, disc + tot + 1, x) - disc - 1], 1, n, l, r)) << '\n';
    }
    return ;
}

分块也可以,口胡了一下对每块存储值域的前缀和,大概是 \(O(n\sqrt n + q\sqrt n)\) 的。

XY_Eleven大佬写了一个二维树状数组,可以考虑用前缀和转化为 \(1\sim r\)\(1\sim x\) 的数的和,然后用二维数据结构维护即可,时间复杂度是 \(O(n\log^2n + q\log^2n)\) 的。

posted @ 2024-02-04 19:31  MoyouSayuki  阅读(23)  评论(0编辑  收藏  举报
:name :name