Submission #378382

#TimeUsernameProblemLanguageResultExecution timeMemory
378382mihai145Election Campaign (JOI15_election_campaign)C++14
100 / 100
265 ms49248 KiB
#include <iostream>
#include <vector>

using namespace std;

const int NMAX = 1e5;
const int LGMAX = 17;

int N, M;
vector <int> g[NMAX + 2], gNoDad[NMAX + 2];

int kTime, timeIn[NMAX + 2], timeOut[NMAX + 2];
int h[NMAX + 2], dad[NMAX + 2], w[NMAX + 2];

int log2[2 * NMAX + 2], firstAp[NMAX + 2];
vector <int> rmq[LGMAX + 2];

void dfs(int node, int parent = 0) {
    dad[node] = parent;
    w[node] = 1;

    ++kTime;
    timeIn[node] = kTime;

    firstAp[node] = (int)rmq[0].size();
    rmq[0].push_back(node);

    for(int son : g[node]) {
        if(son != parent) {
            h[son] = h[node] + 1;
            gNoDad[node].push_back(son);
            dfs(son, node);
            w[node] += w[son];
            rmq[0].push_back(node);
        }
    }

    timeOut[node] = kTime;
}

int getMin(int x, int y) {
    if(h[x] < h[y]) {
        return x;
    }

    return y;
}

void buildRmq() {
    for(int i = 2; i <= 2 * N; i++) {
        log2[i] = log2[i / 2] + 1;
    }

    for(int i = 1; i <= LGMAX; i++) {
        if((1 << i) > (int)rmq[0].size()) {
            return ;
        }

        for(int j = 0; j < (int)rmq[0].size(); j++) {
            if((1 << i) + j > (int)rmq[0].size()) {
                break;
            } else {
                rmq[i].push_back(getMin(rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]));
            }
        }
    }
}

int queryRmq(int x, int y) {
    x = firstAp[x];
    y = firstAp[y];

    if(x > y) {
        swap(x, y);
    }

    int k = log2[y - x + 1];

    return getMin(rmq[k][x], rmq[k][y - (1 << k) + 1]);
}

vector <int> heavyOrder;
int head[NMAX + 2], pos[NMAX + 2], hs[NMAX + 2];

void dfsHeavy(int node, int heavyHead) {
    head[node] = heavyHead;
    heavyOrder.push_back(node);
    pos[node] = (int)heavyOrder.size();

    int heavySon = g[node][0];
    if(g[node].size() == 1) {
        if(g[node][0] == dad[node]) {
            return ;
        }
    } else {
        if(g[node][0] == dad[node]) {
            heavySon = g[node][1];
        }
    }

    for(int son : g[node]) {
        if(son != dad[node]) {
            if(w[son] > w[heavySon]) {
                heavySon = son;
            }
        }
    }

    hs[node] = heavySon;
    dfsHeavy(heavySon, heavyHead);

    for(int son : g[node]) {
        if(son != dad[node] && son != heavySon) {
            dfsHeavy(son, son);
        }
    }
}

int dp[NMAX + 2];

struct Road {
    int x, y, c;
};
vector <Road> roads[NMAX + 2];

struct Fenwick {
    int v[NMAX + 2];

    inline int LSB(int x) {
        return x & (-x);
    }

    void Update(int pos, int val) {
        for(int i = pos; i <= N; i += LSB(i)) {
            v[i] += val;
        }
    }

    int Sum(int pos) {
        if(pos <= 0) {
            return 0;
        }

        int ans = 0;
        for(int i = pos; i > 0; i -= LSB(i)) {
            ans += v[i];
        }

        return ans;
    }

    int Query(int st, int dr) {
        return Sum(dr) - Sum(st - 1);
    }
};
Fenwick aib;

int qr(int x, int y) {
    if(head[x] == head[y]) {
        if(pos[x] > pos[y]) {
            swap(x, y);
        }
        return aib.Query(pos[x], pos[y]);
    }

    if(h[head[x]] < h[head[y]]) {
        swap(x, y);
    }

    int ans = qr(dad[head[x]], y);
    if(pos[x] > pos[head[x]]) {
        ans += aib.Query(pos[head[x]], pos[x]);
    } else {
        ans += aib.Query(pos[x], pos[head[x]]);
    }

    x = head[x];
    ans -= dp[x];
    ans += dp[hs[dad[x]]];

    return ans;
}

void solve(int node, int parent = 0) {
    int sumDpSons = 0;
    for(int son : g[node]) {
        if(son != parent) {
            solve(son, node);
            sumDpSons += dp[son];
        }
    }

    dp[node] = sumDpSons;

    for(Road road : roads[node]) {
        int newDp = road.c;
        pair <int, int> miss = {0, 0};

        if(node != road.x) {
            int st = 0, dr = (int)gNoDad[node].size() - 1, sol = -1;

            while(st <= dr) {
                int mid = (st + dr) >> 1;
                int trg = gNoDad[node][mid];

                if(timeIn[trg] <= timeIn[road.x] && timeOut[road.x] <= timeOut[trg]) {
                    sol = trg;
                    break;
                }

                if(timeIn[trg] > timeOut[road.x]) {
                    dr = mid - 1;
                } else {
                    st = mid + 1;
                }
            }

            miss.first = sol;
            newDp += qr(miss.first, road.x);
            newDp += dp[hs[road.x]];
        }

        if(node != road.y) {
            int st = 0, dr = (int)gNoDad[node].size() - 1, sol = -1;

            while(st <= dr) {
                int mid = (st + dr) >> 1;
                int trg = gNoDad[node][mid];

                if(timeIn[trg] <= timeIn[road.y] && timeOut[road.y] <= timeOut[trg]) {
                    sol = trg;
                    break;
                }

                if(timeIn[trg] > timeOut[road.y]) {
                    dr = mid - 1;
                } else {
                    st = mid + 1;
                }
            }

            miss.second = sol;
            newDp += qr(miss.second, road.y);
            newDp += dp[hs[road.y]];
        }

        newDp = newDp + sumDpSons - dp[miss.first] - dp[miss.second];

        dp[node] = max(dp[node], newDp);
    }

    ///Update for dady!
    if(node != 1) {
        if(head[node] != head[dad[node]]) {
            aib.Update(pos[dad[node]], dp[node]);
        }
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> N;

    for(int i = 1; i < N; i++) {
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }

    dfs(1);
    buildRmq();

    dfsHeavy(1, 1);

    cin >> M;

    for(int i = 1; i <= M; i++) {
        int x, y, c;
        cin >> x >> y >> c;

        int lca = queryRmq(x, y);
        roads[lca].push_back({x, y, c});
    }

    solve(1);

    cout << dp[1] << '\n';
    return 0;
}

Compilation message (stderr)

election_campaign.cpp:15:5: warning: built-in function 'log2' declared as non-function [-Wbuiltin-declaration-mismatch]
   15 | int log2[2 * NMAX + 2], firstAp[NMAX + 2];
      |     ^~~~
#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...