zoukankan      html  css  js  c++  java
  • 【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] << ">
    ";
    
            // cout << "FAQ" << i << "FAQ
    ";
    
            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
    ", Ans[i]);
        }
    
        return 0;
    }
    
  • 相关阅读:
    数据结构之二叉树解析
    并发出体验 -- 解决小规模并发下单的问题
    JDBC事务控制
    数据库中悲观锁与乐观锁的总结实践
    浅析实际项目中对数据库设计的一些思考
    Java中实现多线程的四种方式
    将本地文件上传至github
    git/github 生成密钥
    git常用命令
    解决git每次提交推送都要输入密码
  • 原文地址:https://www.cnblogs.com/ccryolitecc/p/13993761.html
Copyright © 2011-2022 走看看