ABC133 速通

ABC133

A

随便做。

B

判断平方数。

C

如果 \(\lfloor\frac{L}{2019}\rfloor \not= \lfloor\frac{R}{2019}\rfloor\),则答案为 \(0\),否则暴力。

D

第一座山的水量是 \(A_1 + \frac{1}{2}\sum_{i=1}^n(-1)^iA_i\),后面递推。

E

\(dp_i\) 表示 \(i\) 子树以及固定 \(i\) 父亲颜色的答案,则:

\[dp_u = A_{k - 2}^{|E_u| - 1}\prod_{v \in E_u}dp_v \]

答案即 \(A_k^{|E_{root}| + 1}\prod_{v \in E_{root}}dp_v\)

F

对每一个颜色开一个 vector 记录对应颜色边的欧拉序,查询 \(dis_{u, root}\) 时,先把原 \(dis\) 算出来,再利用欧拉序得出系数,把对应颜色的边长修改即可。

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

#define MAXN 100005
#define MAXL 20

using ll = long long;

int n, q;

struct Edge
{
    int u, v, c;
    ll d;
} e[MAXN << 1];
int h[MAXN];
int idx = 0;

int fa[MAXL][MAXN], dep[MAXN];
ll dis[MAXN];

int dfn[MAXN], elt[MAXN << 1];
int eid = 0;

vector<int> eli[MAXN];
vector<ll> cnt[MAXN], sum[MAXN];

void add(int u, int v, int c, ll d)
{
    e[++idx] = {h[u], v, c, d};
    h[u] = idx;
    e[++idx] = {h[v], u, c, d};
    h[v] = idx;
}

void dfs(int p, int f)
{
    fa[0][p] = f;
    dep[p] = dep[f] + 1;
    dfn[p] = eid;
    for (int i = h[p]; i; i = e[i].u)
    {
        if (e[i].v == f)
        {
            continue;
        }
        elt[++eid] = i;
        dis[e[i].v] = dis[p] + e[i].d;
        dfs(e[i].v, p);
        elt[++eid] = -i;
    }
}

int lca(int u, int v)
{
    if (u == v)
    {
        return u;
    }
    if (dep[u] != dep[v])
    {
        if (dep[u] < dep[v])
        {
            swap(u, v);
        }
        for (int i = MAXL - 1; ~i; i--)
        {
            if (dep[fa[i][u]] > dep[v])
            {
                u = fa[i][u];
            }
        }
        u = fa[0][u];
    }
    if (u == v)
    {
        return u;
    }
    for (int i = MAXL - 1; ~i; i--)
    {
        if (fa[i][u] != fa[i][v])
        {
            u = fa[i][u];
            v = fa[i][v];
        }
    }
    return fa[0][u];
}

ll solve(int p, int u, ll v)
{
    ll res = dis[p];
    int idx = upper_bound(eli[u].begin(), eli[u].end(), dfn[p]) - eli[u].begin() - 1;
    if (idx < 0)
    {
        return res;
    }
    return res - sum[u][idx] + v * cnt[u][idx];
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> q;
    for (int i = 1; i < n; i++)
    {
        int u, v, c;
        ll d;
        cin >> u >> v >> c >> d;
        add(u, v, c, d);
    }
    dfs(1, 1);
    for (int k = 1; k < MAXL; k++)
    {
        for (int i = 1; i <= n; i++)
        {
            fa[k][i] = fa[k - 1][fa[k - 1][i]];
        }
    }
    for (int i = 1; i <= eid; i++)
    {
        if (elt[i] > 0)
        {
            int c = e[elt[i]].c;
            eli[c].push_back(i);
            if (cnt[c].size())
            {
                cnt[c].push_back((*cnt[c].rbegin()) + 1);
                sum[c].push_back((*sum[c].rbegin()) + e[elt[i]].d);
            }
            else
            {
                cnt[c].push_back(1);
                sum[c].push_back(e[elt[i]].d);
            }
        }
        else
        {
            int c = e[-elt[i]].c;
            eli[c].push_back(i);
            cnt[c].push_back((*cnt[c].rbegin()) - 1);
            sum[c].push_back((*sum[c].rbegin()) - e[-elt[i]].d);
        }
    }
    while (q--)
    {
        int x, y, u;
        ll v;
        cin >> u >> v >> x >> y;
        int l = lca(x, y);
        cout << solve(x, u, v) + solve(y, u, v) - 2 * solve(l, u, v) << '\n';
    }
    cout.flush();
    return 0;
}

posted @ 2024-08-24 19:59  cosf  阅读(20)  评论(0)    收藏  举报