Submission #140359

#TimeUsernameProblemLanguageResultExecution timeMemory
140359darkkcyanIdeal city (IOI12_city)C++14
0 / 100
36 ms4732 KiB
#include <bits/stdc++.h>
using namespace std;
using namespace std::placeholders;

#define llong long long 
#define xx first
#define yy second
#define len(x) ((int)x.size())
#define rep(i,n) for (int i = -1; ++ i < n; )
#define rep1(i,n) for (int i = 0; i ++ < n; )
#define all(x) x.begin(), x.end()
// #define rand __rand
// mt19937 rng(chrono::system_clock::now().time_since_epoch().count());  // or mt19937_64
// template<class T = int> T rand(T range = numeric_limits<T>::max()) {
    // return (T)(rng() % range);
// }


int DistanceSum(int n, int *x, int *y) {
    map<pair<int, int>, int> points;
    rep(i, n) points[{x[i], y[i]}] = i;

    struct Dsu {
        vector<int> root;
        Dsu(int n_): root(n_) {
            rep(i, len(root)) root[i] = i;
        }

        int find_set(int u) { return u == root[u] ? u : root[u] = find_set(root[u]); }
        void join(int u, int v) {
            if (rand() & 1) swap(u, v);
            // clog << "join " << u << ' ' << v << endl;
            root[find_set(u)] = find_set(v);
        }
    };

    Dsu dsu(n);
    rep(i, n) {
        if (points.count({x[i] + 1, y[i]})) {
            dsu.join(points[{x[i] + 1, y[i]}], i);
        }
    }

    vector<set<int>> gr(n);
    rep(i, n) {
        auto f = points.find({x[i], y[i] + 1});
        if (f == points.end()) continue;
        int u = dsu.find_set(i);
        int v = dsu.find_set(f->yy);
        gr[u].insert(v);
        gr[v].insert(u);
    }

    vector<pair<int, int>> gr_range(n, {INT_MAX, INT_MIN});
    rep(i, n) {
        int r = dsu.find_set(i);
        gr_range[r].xx = min(gr_range[r].xx, x[i]);
        gr_range[r].yy = max(gr_range[r].yy, x[i]);
    }

    auto intersect = [](pair<int, int> const& range1, pair<int, int> const& range2) -> pair<int, int> {
        assert(range1.xx <= range2.yy);
        assert(range2.xx <= range1.yy);
        return {max(range1.xx, range2.xx), min(range1.yy, range2.yy)};
    };

    vector<vector<llong>> dp(n);
    vector<int> tree_size(n);

    llong minus_ans = 0;

    function<void(int, int)> dfs = [&](int u, int p) {
        int cnt = gr_range[u].yy - gr_range[u].xx + 1;
        tree_size[u] = cnt;
        dp[u].resize(cnt);

        rep(i, cnt) {
            dp[u][i] = 1ll * i * (i + 1) / 2  + 1ll * (cnt - 1 - i) * (cnt - i) / 2ll;
            minus_ans += 1ll * i * (i + 1) / 2;
        }

        vector<llong> diff1(cnt), diff1_r(cnt);
        vector<llong> diff2(cnt), diff2_r(cnt);

        for (auto v: gr[u]) {
            if (v == p) continue;
            dfs(v, u);

            tree_size[u] += tree_size[v];

            auto inter = intersect(gr_range[u], gr_range[v]);
            // clog << "dfs inter " << u << ' ' << p << ":" << inter.xx << ' ' << inter.yy << endl;

            for (int i = inter.xx; i <= inter.yy; ++i) {
                int ux = i - gr_range[u].xx, vx = i - gr_range[v].xx;
                dp[u][ux] += dp[v][vx] + tree_size[v];
            }
            
            int t;
            t = inter.xx - gr_range[u].xx - 1;
            if (t >= 0) {
                diff1_r[t] += dp[v][inter.xx - gr_range[v].xx] + tree_size[v];
                diff2_r[t] += tree_size[v];
            }

            t = inter.yy - gr_range[u].xx + 1;
            if (t < cnt) {
                diff1[t] += dp[v][inter.yy - gr_range[v].xx] + tree_size[v];
                diff2[t] += tree_size[v];
            }
        }
        // clog << "dfs " << u << ' ' << p << endl;
        // rep(i, cnt) clog << diff1[i] << ' '; clog << endl;
        // rep(i, cnt) clog << diff2[i] << ' '; clog << endl;
        // rep(i, cnt) clog << diff1_r[i] << ' '; clog << endl;
        // rep(i, cnt) clog << diff2_r[i] << ' '; clog << endl;

        rep(i, cnt - 1) {
            diff1[i + 1] += diff1[i];
            diff2[i + 1] += diff2[i];
        }

        for (int i = cnt - 1; i > 0; --i) {
            diff1_r[i - 1] += diff1_r[i];
            diff2_r[i - 1] += diff2_r[i];
        }

        rep(i, cnt - 1) diff2[i + 1] += diff2[i];
        for (int i = cnt - 1; i > 0; --i) diff2_r[i - 1] += diff2_r[i];

        rep(i, cnt) dp[u][i] += diff1[i] + diff2[i] + diff1_r[i] + diff2_r[i];
        
        // rep(i, cnt) clog << dp[u][i] << ' ';
        // clog << endl;
    };

    dfs(dsu.find_set(0), -1);
    llong ans = 0;
    for (auto& i: dp) for (auto f: i) ans += f;

    ans -= minus_ans;
    return (int)(ans % (1000 * 1000 * 1000));
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...