Submission #1220341

#TimeUsernameProblemLanguageResultExecution timeMemory
1220341LucaIliePetrol stations (CEOI24_stations)C++20
18 / 100
3594 ms15576 KiB
#include <bits/stdc++.h>

using namespace std;

struct edge {
    int u, v, c;

    int other(int w) {
        return u ^ v ^ w;
    }
};

struct SEG_TREE {
    int ls, rs;
    int root;
    vector<int> segTree, leftSon, rightSon;
    vector<int> brut;

    void init(int l, int r) {
        ls = l;
        rs = r;
        segTree.resize(1);
        leftSon.resize(1);
        rightSon.resize(1);
        root = 0;
        segTree[root] = 0;
        leftSon[root] = rightSon[root] = -1;
        brut.clear();
        brut.resize(r + 1);
    }

    int createNode() {
        int v = segTree.size();
        segTree.push_back(0);
        leftSon.push_back(-1);
        rightSon.push_back(-1);
        return v;
    }

    void update(int v, int l, int r, int p, int x) {
        if (l > p || r < p)
            return;

        if (l == r) {
            segTree[v] += x;
            return;
        }

        if (leftSon[v] == -1)
            leftSon[v] = createNode();
        if (rightSon[v] == -1)
            rightSon[v] = createNode();

        int mid = (l + r) / 2;
        update(leftSon[v], l, mid, p, x);
        update(rightSon[v], mid + 1, r, p, x);
        segTree[v] = segTree[leftSon[v]] + segTree[rightSon[v]];
    }

    int query(int v, int l, int r, int lq, int rq) {
        if (v == -1)
            return 0;

        if (l > rq || r < lq)
            return 0;

        if (lq <= l && r <= rq)
            return segTree[v];

        int mid = (l + r) / 2;
        return query(leftSon[v], l, mid, lq, rq) + query(rightSon[v], mid + 1, r, lq, rq);
    }

    void modify(int p, int x) {
        // printf("mod %d %d\n", p, x);
        brut[p] += x;
        // update(root, ls, rs, p, x);
    }

    int countLower(int p) {
        int cnt = 0;
        for (int i = 0; i < p; i++)
            cnt += brut[i];
        return cnt;
        // p--;
        // return query(root, ls, rs, 0, p);
    }
};

const int MAX_N = 7e4;
int k;
long long ans[MAX_N];
bool isCentroid[MAX_N];
int sizee[MAX_N], depth[MAX_N], starts[MAX_N];
int remUp[MAX_N];
edge edges[MAX_N];
vector<int> adj[MAX_N];
SEG_TREE frecv;

void calcSizes(int u, int p) {
    sizee[u] = 1;
    for (int e: adj[u]) {
        int v = edges[e].other(u);
        if (v == p || isCentroid[v])
            continue;
        calcSizes(v, u);
        sizee[u] += sizee[v];
    }
}

int totsz, centroid;
void findCentroid(int u, int p) {
    int maxsz = totsz - sizee[u];
    for (int e: adj[u]) {
        int v = edges[e].other(u);
        if (v == p || isCentroid[v])
            continue;
        findCentroid(v, u);
        maxsz = max(maxsz, sizee[v]);
    }
    if (maxsz <= totsz / 2)
        centroid = u;
}

vector<int> vert, st, vertBySubtree[MAX_N];
void calcUp(int u, int p, int w) {
    if (p != -1 && w == -1)
        w = u;

    vert.push_back(u);
    st.push_back(u);
    if (p != -1)
        vertBySubtree[w].push_back(u);

    int l = -1, r = st.size() - 1;
    while (r - l > 1) {
        int mid = (l + r) / 2;
        if (depth[u] - depth[st[mid]] <= k)
            r = mid;
        else
            l = mid;
    }
    remUp[u] = (r == 0 ? k - depth[u] : remUp[st[r]]);

    sizee[u] = 1;
    for (int e: adj[u]) {
        int v = edges[e].other(u);
        if (v == p || isCentroid[v])
            continue; 
        depth[v] = depth[u] + edges[e].c;
        calcUp(v, u, w);
        sizee[u] += sizee[v];
    }

    if (r != 0)
        starts[st[r]] += starts[u] + 1;    


    // printf("%d %lld %d %d\n", u, ans[u], sizee[u], sizee[w]);

    st.pop_back();
}

void calcDown(int u, int p) {
    int st = frecv.countLower(depth[u]) - frecv.countLower(depth[p]);
    // printf("ciic %d %d %d %d\n", u, p, st, depth[u]);
    ans[p] += (long long)st * sizee[u];
    frecv.modify(k + depth[p], st);

    for (int e: adj[u]) {
        int v = edges[e].other(u);
        if (v == p)
            continue;
        calcDown(v, u);
    }

    frecv.modify(k + depth[p], -st);
}

void decomp(int r) {
    calcSizes(r, -1);
    totsz = sizee[r];
    findCentroid(r, -1);
    int c = centroid;

    calcUp(c, -1, -1);

    // printf("CEN %d\n", c);
    // for (int v: vert)
    //     printf("%d %d\n", v, remUp[v]);

    for (int e: adj[c]) {
        int w = edges[e].other(c);
        if (isCentroid[w])
            continue;
        for (int v: vertBySubtree[w])
            ans[v] += (long long)(sizee[c] - sizee[w]) * starts[v];
        // printf("%d %d\n", sizee[c], sizee[w]);
    }

    frecv.init(0, (long long)sizee[c] * k);
    for (int v: vert)
        frecv.modify(remUp[v], 1);

    // for (int v: vert)
    //     printf("%d %lld\n", v, ans[v]);

    for (int e: adj[c]) {
        int w = edges[e].other(c);
        if (isCentroid[w])
            continue;

        for (int v: vertBySubtree[w])
            frecv.modify(remUp[v], -1);

        calcDown(w, c);

        for (int v: vertBySubtree[w])
            frecv.modify(remUp[v], 1);

    }

    for (int v: vert) {
        starts[v] = sizee[v] = depth[v] = 0;
        vertBySubtree[v].clear();
    }
    vert.clear();

    isCentroid[c] = true;
    for (int e: adj[c]) {
        int w = edges[e].other(c);
        if (isCentroid[w])
            continue;
        decomp(w);
    }
}

int main() {
    int n;
    
    cin >> n >> k;
    for (int e = 0; e < n - 1; e++) {
        cin >> edges[e].u >> edges[e].v >> edges[e].c;
        adj[edges[e].u].push_back(e);
        adj[edges[e].v].push_back(e);
    }

    frecv.init(0, (long long)n * k);
    decomp(0);

    for (int v = 0; v < n; v++)
        cout << ans[v] << "\n";

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...