【WC2013】糖果公园(树上带修莫队)

Link:
Luogu https://www.luogu.com.cn/problem/P4074


Solution

言い たい ことが あるん だよ!

今天!
我!
把 m 和 q
写着写着
当成一个东西了!!

或许哪一天我又看不懂了我稍微写一写

莫队挂一条欧拉序就可以上树
需要特殊处理一下 LCA
带修就正常地加一条时间轴就可以了

结构体可能开得比较厉害之类的反正写得有点过重
最优解2s 这份代码12s
/kk


Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
using namespace std;
char frBB[1<<12], *frS=frBB, *frT=frBB;
#define getchar() (frS==frT&&(frT=(frS=frBB)+fread(frBB,1,1<<12,stdin),frS==frT)?EOF:*frS++)
double _db_read()
{
    int w = 0; char ch = 0; double x = 0;
    while (!isdigit(ch)) w |= ch == '-', ch = getchar();
    while (isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
    if (ch == '.')
    {
        double y = 1.0; ch = getchar();
        while (isdigit(ch)) x += (y /= 10) * (ch ^ 48), ch = getchar();
    }
    return w ? -x : x;
}
int _n_read()
{
    int w = 0; char ch = 0; int x = 0;
    while (!isdigit(ch)) w |= ch == '-', ch = getchar();
    while (isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
    return w ? -x : x;
}
#define read(x) x=_n_read()

const int MAXM = 2e5 + 10;
const int MAXN = 1e5 + 10;
const int MAXDFN = 3e5 + 10;

int n, m, q;
int v[MAXN];
int w[MAXN];

int tot = 0;
int head[MAXN], nxt[MAXM], to[MAXM];

#define add_edge(u,v) nxt[++tot]=head[u],head[u]=tot,to[tot]=v

int W[MAXN], V[MAXN], C[MAXN];
int depth[MAXN];
int lst[MAXM], in[MAXN], out[MAXN];
int fa[20][MAXN];

int _temp_C[MAXN];
int m_tar[MAXN];
int m_res[MAXN];
int m_prev[MAXN];
int m_tot = 0;

int Bucket[MAXN];

bool vis[MAXN];

int _temp_M = 0;

void DFS(int pos)
{
    lst[++lst[0]] = pos;
    in[pos] = lst[0];

    for (int i = head[pos]; i; i = nxt[i])
    {
        if (to[i] == fa[0][pos]) continue;
        fa[0][to[i]] = pos;
        depth[to[i]] = depth[pos] + 1;
        DFS(to[i]);
    }

    lst[++lst[0]] = pos;
    out[pos] = lst[0];
}

int lca(const int &tx, const int &ty)
{

    if (tx == ty) return tx;

    static int x, y;

    x = tx;
    y = ty;

    if (depth[x] < depth[y]) swap(x, y);

    for (int i = 17; i >= 0; --i)
    {
        if (depth[fa[i][x]] >= depth[y]) 
        {
            x = fa[i][x];
        }
    }

    if (x == y) return x;

    for (int i = 17; i >= 0; --i)
    {
        if (fa[i][x] != fa[i][y])
        {
            x = fa[i][x];
            y = fa[i][y];
        }
    }

    return fa[0][x];
}

int belong[MAXDFN];
int block_siz, block_cnt;

struct s_q
{
    int id, x, y, t, xyLCA, u, v;
    s_q() : id(0), x(0), y(0), t(0), xyLCA(0), u(0), v(0) {}
} sq[MAXN];

const bool cmp (const s_q &a, const s_q &b)
{
    if (belong[a.x] != belong[b.x])
    {
        return belong[a.x] < belong[b.x];
    }
    if (belong[a.y] != belong[b.y])
    {
        return (belong[a.x] & 1) ? (belong[a.y] < belong[b.y]) : (belong[a.y] > belong[b.y]);
    }
    return (belong[a.y] & 1) ? (a.t < b.t) : (a.t > b.t);
}

long long _ans_Temp = 0;
long long Ans[MAXN];

void solve(const int &x)
{
    if (vis[x] ^= 1)
    {
        ++Bucket[C[x]];
        _ans_Temp += 1ll * V[C[x]] * W[Bucket[C[x]]];
        return;
    }
    //else
    _ans_Temp -= 1ll * V[C[x]] * W[Bucket[C[x]]];
    --Bucket[C[x]];
}

int main()
{
    read(n), read(m), read(q);

    for (int i = 1; i <= m; ++i)
    {
        read(V[i]);
    }

    for (int i = 1; i <= n; ++i)
    {
        read(W[i]);
    }

    for (int u, v, i = 1; i < n; ++i)
    {
        read(u), read(v);
        add_edge(u, v);
        add_edge(v, u);
    }

    depth[1] = 1;
    DFS(1);

    for (int i = 1; i <= 17; ++i)
    {
        for (int j = 1; j <= n; ++j)
        {   
            fa[i][j] = fa[i-1][fa[i-1][j]];
        }
    }

    for (int i = 1; i <= n; ++i)
    {
        read(C[i]);
        _temp_C[i] = C[i];
    }

    for (int Type, l, x, y, tx, ty, i = 1; i <= q; ++i)
    {
        read(Type); 
        read(x);
        read(y);

        if (Type) // Type == 1 & Query
        {
            l = lca(x, y);
            if (in[x] > in[y]) swap(x, y);
            if (l == x || l == y)
            {
                tx = in[x], ty = in[y];
            }
            else
            {
                tx = out[x], ty = in[y];
            }
            ++_temp_M;
            sq[_temp_M].xyLCA = l;
            sq[_temp_M].id = _temp_M;
            sq[_temp_M].x = tx;
            sq[_temp_M].y = ty;
            sq[_temp_M].t = m_tot;
            sq[_temp_M].u = x;
            sq[_temp_M].v = y;
            continue;
        }

        // (Type == 0) & Modify
        ++m_tot;
        m_tar[m_tot] = x;
        m_res[m_tot] = y;
        m_prev[m_tot] = _temp_C[m_tar[m_tot]];
        _temp_C[x] = y;
    }

    q = _temp_M;

    block_siz = pow(lst[0], 0.66667);
    for (int block_id = 1, block_pos = 0, i = 1; i <= lst[0]; ++i)
    {
        ++block_pos;
        if (block_pos == block_siz + 1)
        {
            block_pos = 1;
            ++block_id;
        }
        belong[i] = block_id;
    }
    block_cnt = belong[lst[0]];

    sort(sq + 1, sq + 1 + q, cmp);

    int l = 1, r = 0, t = 0;
    for (int i = 1; i <= q; ++i)
    {
        while (t < sq[i].t)
        {
            ++t;
            if (vis[m_tar[t]])
            {
                _ans_Temp -= 1ll * V[C[m_tar[t]]] * W[Bucket[C[m_tar[t]]]];
                --Bucket[C[m_tar[t]]];
                ++Bucket[m_res[t]];
                _ans_Temp += 1ll * V[m_res[t]] * W[Bucket[m_res[t]]];
            }
            C[m_tar[t]] = m_res[t];
        }
        while (t > sq[i].t)
        {
            if (vis[m_tar[t]])
            {
                _ans_Temp -= 1ll * V[C[m_tar[t]]] * W[Bucket[C[m_tar[t]]]];
                --Bucket[C[m_tar[t]]];
                ++Bucket[m_prev[t]];
                _ans_Temp += 1ll * V[m_prev[t]] * W[Bucket[m_prev[t]]];
            }
            C[m_tar[t]] = m_prev[t];
            --t;
        }
        while (l < sq[i].x)
        {
            solve(lst[l]);
            ++l;
        }
        while (l > sq[i].x)
        {
            --l;
            solve(lst[l]);
        }
        while (r < sq[i].y)
        {
            ++r;
            solve(lst[r]);
        }
        while (r > sq[i].y)
        {
            solve(lst[r]);
            --r;
        }
        // for (int i = 1; i <= n; ++i)
        //     cout << '<' << i << ' ' << vis[i] << ">\n";

        // cout << "FAQ" << i << "FAQ\n";

        if (sq[i].u != sq[i].xyLCA && sq[i].v != sq[i].xyLCA)
        {
            solve(sq[i].xyLCA);
            Ans[sq[i].id] = _ans_Temp;
            solve(sq[i].xyLCA);
            continue;
        }


        Ans[sq[i].id] = _ans_Temp;
    }

    for (int i = 1; i <= q; ++i)
    {
        printf("%lld\n", Ans[i]);
    }

    return 0;
}
上一篇:【教程】解决七牛云图片外链生效 - 5402 获取bucket域名失败


下一篇:SAPHANA学习(23):SQL Function(W)