ABC343

基本情况

前四题秒了,但是都有不够优雅的地方

F知道是线段树,但是写不出来,极其绝望

C - 343

C - 343 (atcoder.jp)

更简洁的回文判断

MyCode

bool check_p(i64 x) {
    std::string s(std::to_string(x));
    int n = sz(s);
    for (int i = 0; i < n / 2; i++) {
        if (s[i] != s[n - i - 1]) return false;
    }
    return true;
}

signed main(){

    constexpr int N(1E6 + 10);

    std::cin >> n;
    
    i64 ans(1);

    for (i64 i = 0; i < N; i++) {
        i64 num = i * i * i;
        if (num > n) {std::cout << ans << '\n'; return 0;}
        if (check_p(num)) ans = num;
    }

    std::cout << ans << '\n';

    return 0;
}

STD

int main() {

    i64 N;
    std::cin >> N;
    
    i64 ans = 0;
    for (i64 a = 1; a * a * a <= N; a++) {
        std::string s = std::to_string(a * a * a);
        if (s == std::string(s.rbegin(), s.rend())) {//更简洁的回文判断
            ans = a * a * a;
        }
    }
    std::cout << ans << "\n";
    
    return 0;
}

D - Diversity of Scores

D - Diversity of Scores (atcoder.jp)

不知道map可以erase导致的

MyCode

signed main(){
    int N, T;
    std::cin >> N >> T;
    std::vector<i64> a(N);
    std::set<i64> S(all(a));
    std::map<i64, int> cnt;
    cnt[0] = N;
    for (int _ = 1; _ <= T; _++) {
        int idx; i64 add;
        std::cin >> idx >> add;
        idx--;
        if (cnt.count(a[idx])) {
            cnt[a[idx]]--;
            if (cnt[a[idx]] == 0) {
                S.erase(a[idx]);
            }
        }
        a[idx] += add;
        cnt[a[idx]]++;
        S.insert(a[idx]);
        std::cout << sz(S) << '\n';
    }
    return 0;
}

STD

signed main(){
    int N, T;
    std::cin >> N >> T;
    std::vector<i64> a(N);
    std::map<i64, int> cnt;
    cnt[0] = N;
    for (int _ = 1; _ <= T; _++) {
        int idx; i64 add;
        std::cin >> idx >> add;
        idx--;
        if (--cnt[a[idx]] == 0) cnt.erase(a[idx]);//直接用map执行删除操作就行
        a[idx] += add;
        cnt[a[idx]]++;
        std::cout << sz(cnt) << '\n';
    }
    return 0;
}

F - Second Largest Query

F - Second Largest Query (atcoder.jp)

线段树掌握不到位

这里只需要维护次大值,并不需要主席树

而且也不需要通过map等暴力统计次大值数量,可以优雅地直接用线段树在合并时维护

#include <bits/stdc++.h>

using i64 = long long;
template<class Info>
struct SegmentTree {
    int n;
    std::vector<Info> info;
    SegmentTree() : n(0) {}
    SegmentTree(int n_, Info v_ = Info()) {
        init(n_, v_);
    }
    template<class T>
    SegmentTree(std::vector<T> init_) {
        init(init_);
    }
    void init(int n_, Info v_ = Info()) {
        init(std::vector(n_, v_));
    }
    template<class T>
    void init(std::vector<T> init_) {
        n = init_.size();
        info.assign(4 << std::__lg(n), Info());
        std::function<void(int, int, int)> build = [&](int p, int l, int r) {
            if (r - l == 1) {
                info[p] = init_[l];
                return;
            }
            int m = (l + r) / 2;
            build(2 * p, l, m);
            build(2 * p + 1, m, r);
            pull(p);
        };
        build(1, 0, n);
    }
    void pull(int p) {
        info[p] = info[2 * p] + info[2 * p + 1];
    }
    void modify(int p, int l, int r, int x, const Info &v) {
        if (r - l == 1) {
            info[p] = v;
            return;
        }
        int m = (l + r) / 2;
        if (x < m) {
            modify(2 * p, l, m, x, v);
        } else {
            modify(2 * p + 1, m, r, x, v);
        }
        pull(p);
    }
    void modify(int p, const Info &v) {
        modify(1, 0, n, p, v);
    }
    Info rangeQuery(int p, int l, int r, int x, int y) {
        if (l >= y || r <= x) {
            return Info();
        }
        if (l >= x && r <= y) {
            return info[p];
        }
        int m = (l + r) / 2;
        return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
    }
    Info rangeQuery(int l, int r) {
        return rangeQuery(1, 0, n, l, r);
    }
    template<class F>
    int findFirst(int p, int l, int r, int x, int y, F pred) {
        if (l >= y || r <= x || !pred(info[p])) {
            return -1;
        }
        if (r - l == 1) {
            return l;
        }
        int m = (l + r) / 2;
        int res = findFirst(2 * p, l, m, x, y, pred);
        if (res == -1) {
            res = findFirst(2 * p + 1, m, r, x, y, pred);
        }
        return res;
    }
    template<class F>
    int findFirst(int l, int r, F pred) {
        return findFirst(1, 0, n, l, r, pred);
    }
    template<class F>
    int findLast(int p, int l, int r, int x, int y, F pred) {
        if (l >= y || r <= x || !pred(info[p])) {
            return -1;
        }
        if (r - l == 1) {
            return l;
        }
        int m = (l + r) / 2;
        int res = findLast(2 * p + 1, m, r, x, y, pred);
        if (res == -1) {
            res = findLast(2 * p, l, m, x, y, pred);
        }
        return res;
    }
    template<class F>
    int findLast(int l, int r, F pred) {
        return findLast(1, 0, n, l, r, pred);
    }
};

struct Info {
    int max_1 = -1;
    int cnt_1 = 0;
    int max_2 = -2;
    int cnt_2 = 0;
};

Info operator+(Info a, Info b) {//区间合并维护次大值和次大值个数
    
    if (a.max_1 == b.max_1) {//如果两个区间最大值相等
        if (a.max_2 < b.max_2) {
            std::swap(a, b);
        }   
        a.cnt_1 += b.cnt_1;
        if (a.max_2 == b.max_2) {
            a.cnt_2 += b.cnt_2;
        }
    }
    else {//如果两个区间最大值不等
        if (a.max_1 < b.max_1) {//先把情况变成a最大值最大
            std::swap(a, b);
        }
        if (b.max_1 > a.max_2) {
            //如果b的最大值比a的次大值大(此时a的最大值肯定是最大的,所以b的最大值就是次大值)
            //此时并不用考虑b的次大值,因为该结构要求了次大值严格小于最大值,既然b的最大值已经小于a了,那么b的次大值只能更小
            a.max_2 = b.max_1;//维护次大值
            a.cnt_2 = b.cnt_1;//显然次大值改变了,所以个数改成b的最大值的个数
        }
        else if (b.max_1 == a.max_2) {//两个都是次大值,就相加
            a.cnt_2 += b.cnt_1;
        }
    }
    return a; 
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int N, Q;
    std::cin >> N >> Q;
    
    std::vector<int> A(N);
    for (int i = 0; i < N; i++) {
        std::cin >> A[i];
    }
    
    SegmentTree<Info> seg(N);

    for (int i = 0; i < N; i++) {
        seg.modify(i, {A[i], 1, -1, 0});//单点修改,最大值等于自己,个数为1.没有次大值,所以设成{0, 1}
    }

    while(Q--) {
        int o;
        std::cin >> o;

        if (o == 1) {
            int p, x;
            std::cin >> p >> x;
            p--;
            seg.modify(p, {x, 1, -1, 0});
        }
        else {
            int l, r;
            std::cin >> l >> r;
            l--;//左闭右开
            std::cout << seg.rangeQuery(l, r).cnt_2 << '\n';
        }
    }

    return 0;
}

E - 7x7x7

https://atcoder.jp/contests/abc343/tasks/abc343_e

人类智慧枚举

不难得出:

  • 如果三个立方体完全不交,根本没有枚举的意义。
  • 固定第一个顶点,不影响答案

所以枚举剩下两个立方体的顶点,\([-7, 7]\)

对于求两两相交的总体积,显然是分别求之后再减去三倍(三三相交)的体积。

对于求不相交的总体积,显然是 \(3\times 7\times 7\times 7 - 2\times V_2 - 3\times V_3\)

struct Cube {
    int x, y, z;
    Cube(){}
    Cube(int _x, int _y, int _z) : x(_x), y(_y), z(_z){}
    friend std::ostream& operator<<(std::ostream& os, const Cube& cube) {
        os << cube.x << ' ' << cube.y << ' ' << cube.z;
        return os;
    }
};

signed main()
{
    std::cin.tie(nullptr)->sync_with_stdio(false);
    std::array<int, 3> v; for (auto& x : v) {std::cin >> x;}
    
    std::vector<Cube> C(3);

    C[0] = Cube(0, 0, 0);
    auto F_2 = [&](Cube& c1, Cube& c2) {
        int res = 1;
        res *= std::max(0, std::min(c1.x, c2.x) + 7 - ranges::max(c1.x, c2.x));
        res *= std::max(0, std::min(c1.y, c2.y) + 7 - ranges::max(c1.y, c2.y));
        res *= std::max(0, std::min(c1.z, c2.z) + 7 - ranges::max(c1.z, c2.z));
        return res;
    };

    auto F_3 = [&](Cube& c1, Cube& c2, Cube& c3) {
        int res = 1;
        res *= std::max(0, std::min({c1.x, c2.x, c3.x}) + 7 - std::max({c1.x, c2.x, c3.x}));
        res *= std::max(0, std::min({c1.y, c2.y, c3.y}) + 7 - std::max({c1.y, c2.y, c3.y}));
        res *= std::max(0, std::min({c1.z, c2.z, c3.z}) + 7 - std::max({c1.z, c2.z, c3.z}));
        return res;
    };

    L(a1, -7, 7) L(b1, -7, 7) L(c1, -7, 7) L(a2, -7, 7) L(b2, -7, 7) L(c2, -7, 7) {
        C[1] = Cube(a1, b1, c1); C[2] = Cube(a2, b2, c2); 
        std::array<int, 3> V;
        V[2] = F_3(C[0], C[1], C[2]); 
        V[1] = F_2(C[0], C[1]) + F_2(C[0], C[2]) + F_2(C[1], C[2]) - V[2] * 3;
        V[0] = 3 * 7 * 7 * 7 - V[1] * 2 - V[2] * 3;
        if (v == V) {
            std::cout << "Yes\n";    
            for (auto& cube : C) {std::cout << cube << ' ';}
            return 0;
        }
    }
    std::cout << "No\n";
    return 0;
}
posted @ 2024-03-02 23:36  加固文明幻景  阅读(236)  评论(0编辑  收藏  举报