QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#462567#3226. Distance SumpropaneTL 2799ms114108kbC++2010.3kb2024-07-03 21:00:182024-07-03 21:00:19

Judging History

This is the latest submission verdict.

  • [2024-07-03 21:00:19]
  • Judged
  • Verdict: TL
  • Time: 2799ms
  • Memory: 114108kb
  • [2024-07-03 21:00:18]
  • 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 += x.len * f.sum - 2 * x.dep * f.cnt;
    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 << get(last) <<  '\n';
    }

}

詳細信息

Test #1:

score: 100
Accepted
time: 0ms
memory: 3520kb

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
6
8
9
11
12
14

result:

ok 10 lines

Test #2:

score: 0
Accepted
time: 0ms
memory: 3552kb

input:

10
5 1
10 1
5 1
3 1
5 1
5 1
1 1
3 1
1 1

output:

0
4
4
6
6
7
8
12
14
16

result:

ok 10 lines

Test #3:

score: 0
Accepted
time: 0ms
memory: 3604kb

input:

10
4 1
7 1
9 1
3 1
7 1
1 1
7 1
6 1
3 1

output:

0
5
6
9
11
12
12
13
15
17

result:

ok 10 lines

Test #4:

score: 0
Accepted
time: 0ms
memory: 3548kb

input:

10
1 1
9 1
9 1
6 1
9 1
3 1
10 1
1 1
3 1

output:

0
1
3
5
7
8
10
13
13
15

result:

ok 10 lines

Test #5:

score: 0
Accepted
time: 0ms
memory: 3624kb

input:

10
6 1
6 1
3 1
3 1
1 1
1 1
9 1
3 1
1 1

output:

0
2
3
5
6
7
9
12
13
16

result:

ok 10 lines

Test #6:

score: 0
Accepted
time: 0ms
memory: 3608kb

input:

10
8 1
10 1
6 1
3 1
1 1
1 1
4 1
5 1
4 1

output:

0
4
6
6
9
10
13
14
18
19

result:

ok 10 lines

Test #7:

score: 0
Accepted
time: 0ms
memory: 3592kb

input:

10
5 1
8 1
9 1
1 1
1 1
5 1
5 1
1 1
1 1

output:

0
2
4
7
7
9
10
11
13
15

result:

ok 10 lines

Test #8:

score: 0
Accepted
time: 0ms
memory: 3492kb

input:

10
5 1
5 1
8 1
4 1
5 1
4 1
1 1
2 1
7 1

output:

0
4
5
6
6
7
9
11
13
16

result:

ok 10 lines

Test #9:

score: 0
Accepted
time: 0ms
memory: 3628kb

input:

10
4 1
1 1
3 1
3 1
5 1
6 1
6 1
8 1
4 1

output:

0
3
3
4
5
7
10
13
16
19

result:

ok 10 lines

Test #10:

score: 0
Accepted
time: 0ms
memory: 3620kb

input:

10
8 1
10 1
8 1
4 1
9 1
10 1
1 1
8 1
8 1

output:

0
2
4
5
7
9
11
11
12
13

result:

ok 10 lines

Test #11:

score: 0
Accepted
time: 2799ms
memory: 114108kb

input:

200000
109891 65231
171839 5776
32431 29819
62570 71905
153470 68881
188361 76298
151469 77636
75162 130242
95864 47113
191182 742
121927 111781
18165 51034
158645 36001
193496 189958
143195 29723
140274 86466
117583 23287
184465 144332
35935 128306
192514 116854
27679 197718
138926 123165
46773 177...

output:

0
2128476
3615067
4333135
5793589
7104606
7876598
9621410
10959705
12443304
12989537
15017823
15660417
16551255
18007974
18487621
20027188
21203385
22454974
22931660
23796204
25173856
26195907
27604778
28662852
29446260
30856590
32645490
33338651
34979442
36020161
37417274
38263592
39224218
40460394...

result:

ok 200000 lines

Test #12:

score: -100
Time Limit Exceeded

input:

200000
196697 155143
178488 159177
49016 18473
171950 94863
69271 100194
160889 20733
40420 19766
191138 127108
142060 2610
194472 41608
6942 105158
61037 3025
150904 197834
58272 30296
5859 116513
104509 1986
48140 173435
131223 123177
175812 40180
28608 98965
157005 67994
127784 114441
17436 68620...

output:

0
11320917384
11874614449
15772614655
18523775058
21957641652
30009559722
31970095838
35324661901
38253652284
48493111245
51933582990
58121449414
67628507769
73905238960
83828871781
83828871781
86351127383
86906418351
88386492876
89035727731
94945127602
103238157194
103565667357
106031510890
1148471...

result: