QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#462538#3226. Distance SumpropaneWA 0ms3544kbC++2010.3kb2024-07-03 20:39:252024-07-03 20:39:26

Judging History

This is the latest submission verdict.

  • [2024-07-03 20:39:26]
  • Judged
  • Verdict: WA
  • Time: 0ms
  • Memory: 3544kb
  • [2024-07-03 20:39:25]
  • Submitted

answer

#include<iostream>
#include<cstring>
#include<vector>
#include<numeric>
#include<functional>
#include<algorithm>
using namespace std;
using LL = long long;

// d(u, v) = dep(u) + dep(v) - 2 dep(anc)
// 维护一个点的子树内已经有的深度和 减去两倍的本身深度 以及点的个数
// 因为会重复,所以需要类似点分树维护子树的贡献,减去避免重复计数

struct Info{
    LL dep = 0, len = 0, cnt = 0, sum = 0;
};

struct Tag{
    LL cnt = 0, sum = 0;
};

Info operator+(const Info &a, const Info &b){
    return {a.dep + b.dep, a.len + b.len, a.cnt + b.cnt, a.sum + b.sum};
}

void apply(Info &x, Tag &a, Tag f){
    x.cnt += x.len * f.cnt;
    x.sum -= 2 * x.dep * f.cnt;
    x.sum += x.len * f.sum;
    a.cnt += f.cnt;
    a.sum += f.sum; 
}

template<class Info, class Tag>
struct LazySegmentTree{
    int n;
    vector<Info> info;
    vector<Tag> tag;

    LazySegmentTree() {}

    LazySegmentTree(int n, Info _init = Info()){
        init(vector<Info>(n, _init));
    }

    LazySegmentTree(const vector<Info> &_init){
        init(_init);
    }

    void init(const vector<Info> &_init){
        n = (int)_init.size();
        info.assign((n << 2) + 1, Info());
        tag.assign((n << 2) + 1, Tag());
        function<void(int, int, int)> build = [&](int p, int l, int r){
            if (l == r){
                info[p] = _init[l - 1];
                return;
            }
            int m = (l + r) / 2;
            build(2 * p, l, m);
            build(2 * p + 1, m + 1, r);
            pull(p);
        };
        build(1, 1, n);
    }
    
    void pull(int p){
        info[p] = info[2 * p] + info[2 * p + 1];
    }
    
    void apply(int p, const Tag &v){
        ::apply(info[p], tag[p], v);
    }
    
    void push(int p){
        apply(2 * p, tag[p]);
        apply(2 * p + 1, tag[p]);
        tag[p] = Tag();
    }
    
    void modify(int p, int l, int r, int x, const Info &v){
        if (l == r){
            info[p] = v;
            return;
        }
        int m = (l + r) / 2;
        push(p);
        if (x <= m){
            modify(2 * p, l, m, x, v);
        } 
        else{
            modify(2 * p + 1, m + 1, r, x, v);
        }
        pull(p);
    }
    
    void modify(int p, const Info &v){
        modify(1, 1, n, p, v);
    }
    
    Info query(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;
        push(p);
        return query(2 * p, l, m, x, y) + query(2 * p + 1, m + 1, r, x, y);
    }
    
    Info query(int l, int r){
        return query(1, 1, n, l, r);
    }
    
    void modify(int p, int l, int r, int x, int y, const Tag &v){
        if (l > y || r < x){
            return;
        }
        if (l >= x && r <= y){
            apply(p, v);
            return;
        }
        int m = (l + r) / 2;
        push(p);
        modify(2 * p, l, m, x, y, v);
        modify(2 * p + 1, m + 1, r, x, y, v);
        pull(p);
    }
    
    void modify(int l, int r, const Tag &v){
        return modify(1, 1, n, l, r, v);
    }
};

// 1_based HLD
struct Edge{
    int to;
    int w;
    operator int() const { return to; }
};

struct HLD{
    int n;
    vector<int> sz, top, dep, fa, in, out, seq;
    vector<LL> dis;
    vector<vector<Edge> > g;
    int ts;

    HLD(const vector<vector<Edge> > &g, int root = 1) : n(int(g.size()) - 1), g(g)  {
        ts = 0;
        sz.resize(n + 1);
        top.resize(n + 1);
        dep.resize(n + 1);
        fa.resize(n + 1);
        in.resize(n + 1);
        out.resize(n + 1);
        seq.resize(n + 1);
        dis.resize(n + 1);
        dep[root] = 1;
        top[root] = root;
        dfs_sz(root);
        dfs_hld(root);
    }

    void dfs_sz(int u){
        if (fa[u]){
            for(auto it = g[u].begin(); it != g[u].end(); it++){
                if (*it == fa[u]){
                    g[u].erase(it);
                    break;
                }
            }
        }
        sz[u] = 1;
        for(auto &j : g[u]){
            fa[j] = u;
            dep[j] = dep[u] + 1;
            dis[j] = dis[u] + j.w;
            dfs_sz(j);
            sz[u] += sz[j];
            if (sz[j] > sz[g[u][0]])
                swap(j, g[u][0]);
        }
    }

    void dfs_hld(int u){
        in[u] = ++ts;
        seq[in[u]] = u;
        for (auto j : g[u]){
            top[j] = (j == g[u][0] ? top[u] : j);
            dfs_hld(j);
        }
        out[u] = ts;
    }

    int lca(int u, int v){
        while (top[u] != top[v]){
            if (dep[top[u]] > dep[top[v]]){
                u = fa[top[u]];
            } 
            else{
                v = fa[top[v]];
            }
        }
        return dep[u] < dep[v] ? u : v;
    }

    int dist(int u, int v){
        return dep[u] + dep[v] - 2 * dep[lca(u, v)];
    }

    bool in_subtree(int u, int v){
        return in[v] <= in[u] && in[u] <= out[v];
    }
    
    int jump(int u, int k) {
        if (dep[u] < k){
            return -1;
        }
        int d = dep[u] - k;
        while (dep[top[u]] > d){
            u = fa[top[u]];
        }
        return seq[in[u] - dep[u] + d];
    }
    
    int rooted_lca(int a, int b, int c){
        return lca(a, b) ^ lca(b, c) ^ lca(c, a);
    }

    template<typename Q>
    void modify_path(int u, int v, const Q &q, bool edge = false){
        while(top[u] != top[v]){
            if (dep[top[u]] < dep[top[v]]) swap(u, v);
            q(in[top[u]], in[u]);
            u = fa[top[u]];        
        }
        if (dep[u] > dep[v]) swap(u, v);
        q(in[u] + edge, in[v]);
    }

    template<typename Q>
    void modify_subtree(int u, const Q &q){
        q(in[u], out[u]);
    }  

    template<typename T, typename Q>
    T query_path(int u, int v, const Q &q, bool edge = false){
        T ret = T();
        while(top[u] != top[v]){
            if (dep[top[u]] < dep[top[v]]) swap(u, v);
            ret = q(in[top[u]], in[u]) + ret;
            u = fa[top[u]];
        }
        if (dep[u] > dep[v]) swap(u, v);
        return q(in[u] + edge, in[v]) + ret;
    }

    template<typename T, typename Q>
    T query_subtree(int u, const Q &q){
        return q(in[u], out[u]);
    }

    template<typename T, typename Q, typename F>
    T query_path_noncommutative(int u, int v, const Q &q, const F &f, bool edge = false){
        T left = T(), right = T();
        while(top[u] != top[v]){
            if (dep[top[u]] < dep[top[v]]) swap(u, v), swap(left, right);
            left = q(in[top[u]], in[u]) + left;
            u = fa[top[u]];
        }
        if (dep[u] > dep[v]) swap(u, v), swap(left, right);
        return f(left, q(in[u] + edge, in[v]) + right);
    }
    
    pair<vector<int>, vector<pair<int, int> > > compress(vector<int> v){
        auto cmp = [&](int a, int b) { return in[a] < in[b]; };
        sort(v.begin(), v.end(), cmp);
        v.erase(unique(v.begin(), v.end()), v.end());
        const int k = (int)v.size();
        for(int i = 0; i + 1 < k; i++){
            v.push_back(lca(v[i], v[i + 1]));
        }
        sort(v.begin(), v.end(), cmp);
        v.erase(unique(v.begin(), v.end()), v.end());
        vector<pair<int, int> > edges;
        vector<int> stk;
        for(auto x : v){
            while(!stk.empty() && out[stk.back()] < in[x]){
                stk.pop_back();
            }
            if (!stk.empty()){
                edges.push_back({stk.back(), x});
            }
            stk.push_back(x);
        }
        return {v, edges};
    }

};

int main(){

#ifdef LOCAL
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif

    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);

    int n;
    cin >> n;
    vector<vector<Edge> > g(n + 1);
    for(int i = 2; i <= n; i++){
        int p, w;
        cin >> p >> w;
        g[p].push_back({i, w});
    }
    HLD hld(g);
    vector<Info> init1(n), init2(n);
    for(int i = 1; i <= n; i++){
        int x = hld.seq[i];
        init1[i - 1] = {hld.dis[x], 1, 0, 0};
    }
    for(int i = 2; i <= n; i++){
        int x = hld.fa[hld.seq[i]];
        init2[i - 1] = {hld.dis[x], 1, 0, 0};
    }

    LazySegmentTree<Info, Tag> seg1(init1), seg2(init2);

    auto change = [&](int x){

        {
            auto f = [&](int l, int r){
                seg1.modify(l, r, {1, hld.dis[x]});
            };

            hld.modify_path(1, x, f);
        }

        if (x != 1){
            auto f = [&](int l, int r){
                seg2.modify(l, r, {1, hld.dis[x]});
            };

            int t = hld.jump(x, hld.dep[x] - hld.dep[1] - 1);
            hld.modify_path(t, x, f);
        }
    };

    auto get = [&](int x){
        Info res1 = Info(), res2 = Info();
        {
            auto q = [&](int l, int r){
                return seg1.query(l, r);
            };

            res1 = hld.query_path<Info>(1, x, q);
        }
        {
            auto q = [&](int l, int r){
                return seg2.query(l, r);
            };

            res2 = hld.query_path<Info>(1, x, q);
        }
        LL cnt = res1.cnt - res2.cnt;
        LL sum = res1.sum - res2.sum;
        return sum + cnt * hld.dis[x];
    };

    cout << 0 << '\n';
    int last = 1;
    change(1);
    for(int i = 2; i <= n; i++){
        change(i);
        int anc = hld.lca(last, i);
        int len = hld.dep[i] + hld.dep[last] - 2 * hld.dep[anc];

        auto get_pos = [&](int t){
            int x = -1;
            if (t <= hld.dep[last] - hld.dep[anc]){
                x = hld.jump(last, t);
            }
            else{
                x = hld.jump(i, len - t);
            }
            return x;
        };

        auto f = [&](int t){
            return get(get_pos(t));
        };

        int l = 0, r = len;
        while(l < r){
            int m1 = l + (r - l) / 3;
            int m2 = r - (r - l) / 3;
            if (f(m1) >= f(m2)) l = m1 + 1;
            else r = m2 - 1;
        }
        last = get_pos(r);
        cout << f(r) <<  '\n';
    }

}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 0ms
memory: 3544kb

input:

10
5 1
2 1
1 1
4 1
2 1
5 1
2 1
2 1
5 1

output:

0
3
4
6
7
8
9
11
12
14

result:

wrong answer 5th lines differ - expected: '6', found: '7'