結果

問題 No.1919 Many Monster Battles
ユーザー 🍮かんプリン🍮かんプリン
提出日時 2022-04-30 01:51:51
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
RE  
実行時間 -
コード長 7,732 bytes
コンパイル時間 2,310 ms
コンパイル使用メモリ 193,968 KB
実行使用メモリ 45,568 KB
最終ジャッジ日時 2024-06-29 07:47:36
合計ジャッジ時間 19,315 ms
ジャッジサーバーID
(参考情報)
judge4 / judge5
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,816 KB
testcase_01 AC 2 ms
6,940 KB
testcase_02 AC 2 ms
6,944 KB
testcase_03 AC 4 ms
6,948 KB
testcase_04 AC 5 ms
6,940 KB
testcase_05 AC 4 ms
6,940 KB
testcase_06 AC 5 ms
6,944 KB
testcase_07 AC 4 ms
6,944 KB
testcase_08 AC 4 ms
6,940 KB
testcase_09 AC 4 ms
6,944 KB
testcase_10 AC 4 ms
6,944 KB
testcase_11 AC 4 ms
6,944 KB
testcase_12 AC 5 ms
6,944 KB
testcase_13 AC 941 ms
45,568 KB
testcase_14 AC 931 ms
45,440 KB
testcase_15 AC 933 ms
45,440 KB
testcase_16 AC 905 ms
45,440 KB
testcase_17 AC 906 ms
45,440 KB
testcase_18 AC 1,028 ms
29,184 KB
testcase_19 AC 1,045 ms
29,184 KB
testcase_20 AC 1,059 ms
29,312 KB
testcase_21 AC 1,021 ms
29,184 KB
testcase_22 AC 1,014 ms
29,184 KB
testcase_23 AC 573 ms
45,440 KB
testcase_24 AC 576 ms
45,440 KB
testcase_25 AC 586 ms
45,568 KB
testcase_26 AC 583 ms
45,440 KB
testcase_27 AC 377 ms
26,752 KB
testcase_28 AC 379 ms
26,752 KB
testcase_29 AC 375 ms
26,624 KB
testcase_30 AC 375 ms
26,752 KB
testcase_31 AC 603 ms
45,568 KB
testcase_32 AC 604 ms
45,568 KB
testcase_33 RE -
testcase_34 RE -
権限があれば一括ダウンロードができます

ソースコード

diff #

/**
 *   @FileName	a.cpp
 *   @Author	kanpurin
 *   @Created	2022.04.30 01:51:47
**/

#include "bits/stdc++.h" 
using namespace std; 
typedef long long ll;


template< typename Monoid >
struct DynamicSegmentTree {
private:
    struct Node;
    using Func = function<Monoid(Monoid,Monoid)>;
    using node_ptr = unique_ptr<Node>;
    Func F;
    Monoid e;
    size_t n;
    struct Node {
        size_t index;
        Monoid value,prod;
        node_ptr left, right;
        Node(size_t index, Monoid value) : index(index),
                                           value(value),
                                           prod(value),
                                           left(nullptr),
                                           right(nullptr) {}
    };
    
    void node_update(node_ptr &np) const {
        np->prod = F(F(np->left?np->left->prod:e,np->value),
                       np->right?np->right->prod:e);
    }

    void _update(node_ptr& t, size_t a, size_t b, size_t p, Monoid &val) const {
        if (!t) {
            t = make_unique<Node>(p, val);
            return;
        }
        if (t->index == p) {
            t->value = val;
            node_update(t);
            return;
        }
        size_t c = (a+b)/2;
        if (p < c) {
            if (t->index < p) swap(t->index,p), swap(t->value,val);
            _update(t->left,a,c,p,val);
        }
        else {
            if (p < t->index) swap(p,t->index), swap(val,t->value);
            _update(t->right,c,b,p,val);
        }
        node_update(t);
    }

    Monoid _get(const node_ptr& t, size_t a, size_t b, size_t l, size_t r) const {
        if (!t || b <= l || r <= a) return e;
        if (l <= a && b <= r) return t->prod;
        size_t c = (a + b) / 2;
        Monoid result = _get(t->left, a, c, l, r);
        if (l <= t->index && t->index < r) result = F(result, t->value);
        return F(result, _get(t->right, c, b, l, r));
    }

    size_t _binary_search(const node_ptr& t, 
                       size_t a, size_t b, 
                       const function<bool(Monoid)> &f, 
                       Monoid &s, 
                       size_t l, size_t r) {
        if (!t || r <= a || b <= l) return n;
        if (a <= l && r <= b && !f(F(s,t->prod))) {
            s = F(s,t->prod);
            return n;
        }
        size_t ret = _binary_search(t->left,a,b,f,s,l,(r-l)/2+l);
        if (ret != n) return ret;
        if (a <= t->index) {
            s = F(s,t->value);
            if (f(s)) return t->index;
        }
        return _binary_search(t->right,a,b,f,s,(r-l)/2+l,r);
    }

    void _print(node_ptr& t) {
        if (!t) return;
        _print(t->left);
        _print(t->right);
        cout << "[" << t->index << "] : " << t->value << endl;
    }

    node_ptr root;
public:
    DynamicSegmentTree(size_t n,
                       const Func f,
                       const Monoid &e) : n(n),F(f),e(e),root(nullptr) {}

    void update_query(size_t x, Monoid val) {
        assert(x < n);
        _update(root, 0, n, x, val);
    }

    Monoid get_query(size_t l, size_t r) const {
        assert(l <= r && r <= n);
        return _get(root, 0, n, l, r);
    }

    size_t binary_search(size_t l, size_t r, const function<bool(Monoid)> &f) {
        Monoid s = e;
        size_t ret = _binary_search(root,l,r,f,s,0,n);
        return ret != n ? ret : -1;
    }

    Monoid operator[](int x) const {
        return get_query(x,x+1);
    }
    
    size_t size() {
        return n;
    }

    void print() {
        _print(root);
    }
};

template< int MOD >
struct mint {
public:
    unsigned int x;
    mint() : x(0) {}
    mint(long long v) {
        long long w = (long long)(v % (long long)(MOD));
        if (w < 0) w += MOD;
        x = (unsigned int)(w);
    }
    mint(std::string &s) {
        unsigned int z = 0;
        for (int i = 0; i < s.size(); i++) {
            z *= 10;
            z += s[i] - '0';
            z %= MOD;
        }
        x = z;
    }
    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }
    mint& operator+=(const mint &a) {
        if ((x += a.x) >= MOD) x -= MOD;
        return *this;
    }
    mint& operator-=(const mint &a) {
        if ((x -= a.x) >= MOD) x += MOD;
        return *this;
    }
    mint& operator*=(const mint &a) {
        unsigned long long z = x;
        z *= a.x;
        x = (unsigned int)(z % MOD);
        return *this;
    }
    mint& operator/=(const mint &a) {return *this = *this * a.inv(); }
    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs.x == rhs.x;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs.x != rhs.x;
    }
    friend std::ostream& operator<<(std::ostream &os, const mint &n) {
        return os << n.x;
    }
    friend std::istream &operator>>(std::istream &is, mint &n) {
        unsigned int x;
        is >> x;
        n = mint(x);
        return is;
    }
    mint inv() const {
        assert(x);
        return pow(MOD-2);
    }
    mint pow(long long n) const {        
        assert(0 <= n);
        mint p = *this, r = 1;
        while (n) {
            if (n & 1) r *= p;
            p *= p;
            n >>= 1;
        }
        return r;
    }
    
    mint sqrt() const {
        if (this->x < 2) return *this;
        if (this->pow((MOD-1)>>1).x != 1) return mint(0);
        mint b = 1, one = 1;
        while (b.pow((MOD-1) >> 1) == 1) b += one;
        long long m = MOD-1, e = 0;
        while (m % 2 == 0) m >>= 1, e += 1;
        mint x = this->pow((m - 1) >> 1);
        mint y = (*this) * x * x;
        x *= (*this);
        mint z = b.pow(m);
        while (y.x != 1) {
            int j = 0;
            mint t = y;
            while (t != one) j += 1, t *= t;
            z = z.pow(1LL << (e-j-1));
            x *= z; z *= z; y *= z; e = j;
        }
        return x;
    }
};

constexpr int MOD = 1e9 + 7;

int main() {
    int n;cin >> n;
    vector<int> a(n),b(n);
    vector<pair<int,int>> c1(n),c2(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    for (int i = 0; i < n; i++) {
        cin >> b[i];
        c1[i] = {a[i]-b[i]+1000000000,-a[i]-b[i]};
        c2[i] = {a[i]+b[i],a[i]-b[i]-1000000000};
    }
    sort(c1.begin(), c1.end());
    sort(c2.begin(), c2.end());
    DynamicSegmentTree<ll> cnt1(2000000000,[](ll a,ll b){return a+b;},0),sum1(2000000000,[](ll a,ll b){return a+b;},0);
    DynamicSegmentTree<ll> cnt2(2000000000,[](ll a,ll b){return a+b;},0),sum2(2000000000,[](ll a,ll b){return a+b;},0);
    mint<MOD> ans_a = 0, ans_b = 0;
    for (int i = 0; i < n; i++) {
        int v1 = (c1[i].first-1000000000-c1[i].second)/2;
        ans_a += cnt1.get_query(0,-c1[i].second)*v1-sum1.get_query(0,-c1[i].second);
        cnt1.update_query(-c1[i].second,cnt1[-c1[i].second]+1);
        sum1.update_query(-c1[i].second,sum1[-c1[i].second]+v1);
    }
    for (int i = 0; i < n; i++) {
        int v2 = (c2[i].first-c2[i].second-1000000000)/2;
        ans_b += cnt2.get_query(0,-c2[i].second)*v2-sum2.get_query(0,-c2[i].second);
        cnt2.update_query(-c2[i].second,cnt2[-c2[i].second]+1);
        sum2.update_query(-c2[i].second,sum2[-c2[i].second]+v2);
    }
    cout << ans_a*2 << " " << ans_b*2 << endl;
    return 0;
}

0