首页 > 其他分享 >NC200179 Colorful Tree

NC200179 Colorful Tree

时间:2023-06-22 23:22:44浏览次数:53  
标签:dep NC200179 Colorful int tree Tree st leq LCA

题目链接

题目

题目描述

A tree structure with some colors associated with its vertices and a sequence of commands on it are given. A command is either an update operation or a query on the tree. Each of the update operations changes the color of a specified vertex, without changing the tree structure. Each of the queries asks the number of edges in the minimum connected subgraph of the tree that contains all the vertices of the specified color.
Your task is to find answers of each of the queries, assuming that the commands are performed in the given order.

输入描述

The input consists of a single test case of the following format.
n
\(a_1\) \(b_1\)
. . .
\(a_{n−1}\) \(b_{n−1}\)
\(c_1 ... c_n\)
m
\(command_1\)
. . .

\(command_m\)
The first line contains an integer n \((2 \leq n \leq 100000)\) , the number of vertices of the tree. The vertices are numbered 1 through n. Each of the following n−1 lines contains two integers \(a_i (1 \leq a_i \leq n)\) and \(b_i (1 \leq b_i \leq n)\) , meaning that the i-th edge connects vertices \(a_i\) and \(b_i\) . It is ensured that all the vertices are connected, that is, the given graph is a tree. The next line contains n integers, \(c_1\) through \(c_n\) , where \(c_j (1 \leq c_j \leq 100000)\) is the initial color of vertex j. The next line contains an integer m \((1 \leq m \leq 100000)\) , which indicates the number of commands. Each of the following m lines contains a command in the following format.
U \(x_k\) \(y_k\)
or
Q \(y_k\)
When the k-th command starts with U, it means an update operation changing the color of vertex \(x_k (1 \leq x_k \leq n)\) to \(y_k (1 \leq y_k \leq 100000)\) . When the k-th command starts with Q, it
means a query asking the number of edges in the minimum connected subgraph of the tree that contains all the vertices of color \(y_k (1 \leq y_k \leq 100000)\) .

输出描述

For each query, output the number of edges in the minimum connected subgraph of the tree containing all the vertices of the specified color. If the tree doesn’t contain any vertex of the specified color, output -1 instead.

示例1

输入

5 
1 2 
2 3 
3 4 
2 5 
1 2 1 2 3 
11 
Q 1 
Q 2 
Q 3 
Q 4 
U 5 1 
Q 1 
U 3 2 
Q 1 
Q 2 
U 5 4 
Q 1

输出

2 
2 
0 
-1 
3 
2 
2 
0

题解

知识点:DFS序,LCA,STL。

对于一种颜色,我们新加入一个点 \(x\) ,考虑其贡献。设dfn序左右最近的两个点 \(u,v\) ,那么其贡献为:

\[\frac{1}{2}(dist(u,x) + dist(v,x) - dist(u,v)) \]

可以分类讨论验证,首先一定是选择dfn序最近的两点,其次无论 \(x\) 位于 \(u,v\) 中间,还是一侧,这个式子都是满足的。其中对于一侧情况,我们统一取第一个点和最后一个点,可以同时满足左侧和右侧以及只有一个点的情况。

因此,我们对每个颜色的点建一个 set ,排序规则采用dfn序从小到大,更新查找时使用二分即可,增加删除可以写在同一个函数里。对于求距离,使用倍增LCA即可。

初始时,将每个点都加一遍。

时间复杂度 \(O((n+m)\log n)\)

空间复杂度 \(O(n \log n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

struct Graph {
    struct edge {
        int v, nxt;
    };
    int idx;
    vector<int> h;
    vector<edge> e;

    Graph(int n = 0, int m = 0) { init(n, m); }

    void init(int n, int m) {
        idx = 0;
        h.assign(n + 1, 0);
        e.assign(m + 1, {});
    }

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

const int N = 100007;
Graph g;

namespace LCA {
    const int lgN = 16;
    int dep[N], f[lgN + 7][N];
    void dfs(int u, int fa = 0) {
        f[0][u] = fa;
        dep[u] = dep[fa] + 1;
        for (int i = 1;i <= lgN;i++) f[i][u] = f[i - 1][f[i - 1][u]];
        for (int i = g.h[u];i;i = g.e[i].nxt) {
            int v = g.e[i].v;
            if (v == fa) continue;
            dfs(v, u);
        }
    }

    int LCA(int u, int v) {
        if (dep[u] < dep[v]) swap(u, v);
        for (int i = lgN;i >= 0;i--) {
            if (dep[f[i][u]] >= dep[v]) u = f[i][u];
            if (u == v) return u;
        }
        for (int i = lgN;i >= 0;i--) {
            if (f[i][u] != f[i][v]) {
                u = f[i][u];
                v = f[i][v];
            }
        }
        return f[0][u];
    }

    int dis(int u, int v) { return dep[u] + dep[v] - 2 * dep[LCA(u, v)]; }
}

int dfncnt;
int rdfn[N];
void dfs(int u, int fa) {
    rdfn[u] = ++dfncnt;
    for (int i = g.h[u];i;i = g.e[i].nxt) {
        int v = g.e[i].v;
        if (v == fa) continue;
        dfs(v, u);
    }
}

struct cmp {
    bool operator()(int a, int b) const {
        return rdfn[a] < rdfn[b];
    }
};

int c[N];
set<int, cmp> st[N];
int ans[N];

void update(int x, int f) {
    if (f == -1) st[c[x]].erase(x);
    if (st[c[x]].size()) {
        auto it = st[c[x]].lower_bound(x);
        auto it1 = st[c[x]].begin();
        auto it2 = prev(st[c[x]].end());
        if (it != st[c[x]].begin() && it != st[c[x]].end()) {
            it1 = it;
            it2 = prev(it);
        }
        ans[c[x]] += f * (
            LCA::dis(*it1, x)
            + LCA::dis(*it2, x)
            - LCA::dis(*it1, *it2)
            ) / 2;
    }
    if (f == 1) st[c[x]].insert(x);
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    g.init(n, n << 1);
    for (int i = 1;i <= n - 1;i++) {
        int u, v;
        cin >> u >> v;
        g.add(u, v);
        g.add(v, u);
    }
    dfs(1, 0);
    LCA::dfs(1);

    for (int i = 1;i <= n;i++)
        cin >> c[i], update(i, 1);

    int m;
    cin >> m;
    while (m--) {
        char op;
        cin >> op;
        if (op == 'Q') {
            int col;
            cin >> col;
            cout << (st[col].size() ? ans[col] : -1) << '\n';
        }
        else {
            int x, col;
            cin >> x >> col;
            update(x, -1);
            c[x] = col;
            update(x, 1);
        }
    }
    return 0;
}

标签:dep,NC200179,Colorful,int,tree,Tree,st,leq,LCA
From: https://www.cnblogs.com/BlankYang/p/17498556.html

相关文章

  • TreeSaver.js 的工作流程逻辑
    Treesaver是浏览器大小尺寸敏感(size-sensitive)的,会就着当前的浏览器尺寸(browsersize),选用不同的分栏表格(grid)做排版。初始化TreeSaver.js框架的入口源代码在后面可以看到:https://github.com/Treesaver/treesaver/blob/master/src/init.js这里的代码用到了Google开发的JS库:Closur......
  • Win7环境下TreeSaver编译环境的搭配
    首先你需要先搭配出”Win7环境下TreeSaver例子环境的搭配”然后才能继续下一步编译环境。例子环境搭配后,你可以在源代码目录下执行paver命令,搭配例子测试环境,也可以执行paverdebug生成带调试注释信息的treesaver脚本,当然也可以使用paverclean删除生成的文件。这些可以......
  • sourcetree忽略文件
    SourceTree默认使用的是全局缓存配置,这个配置文件在SourceTree–>Preferences–>Git–>GlobalIgnoreList可以看到。如下图:如果想针对某个项目单独做,则请参考下面文章:http://www.ifeegoo.com/git-code-management-dot-gitignore-file-has-no-effect-solution.html 这时......
  • CF383C Propagating tree
    题目链接题目见链接。题解知识点:DFS序,树状数组。我们需要对子树的不同奇偶层加减,用dfn序可以解决子树问题,但是并不能直接分奇偶。一种比较麻烦的思路是,将dfn序分成两个序列,一个是偶数层点序,一个是奇数层点序列,处理两个序列对于某个点作为子树根节点时,开始和结束节点,然后就可......
  • 【vue3】实现el-tree组件
     禾小毅csdn博客【vue3】实现el-tree组件,将不同层级的箭头修改成自定义图标的组件封装及调用【vue3】实现简易的“百度网盘”文件夹的组件封装实现【vue3】实现公共搜索组件,在当前页搜索的路由跳转不能改变当前值的操作,使用bus/event-emitter派发器......
  • linux gpio dev,linux gpio子系统 devicetree中GPIO_ACTIVE_LOW
    一直没怎么理解GPIO_ACTIVE_LOW的作用对于以上的dts你应该再熟悉不过,当然这里不是教你如何使用dts,而是关注gpio和irq最后一个数字可以如何利用。例如rst-gpio的OF_GPIO_ACTIVE_LOW代表什么意思呢?可以理解为低有效。什么意思呢?举个例子,正常情况下,我们需要一个gpio口控制灯,我们认......
  • Vue3 element-Plus el-tree 权限树 传值给后端及回显问题
    内容:权限在新增人员时候选择传给后端并且编辑回显坑:1.传给后端的权限数组需要传父级id例如:一级目录下有二级目录和2-2目录,选了2-2目录,需要把一级目录的id也给后端2.回显的时候后端会把权限数组id都给你(包括一级目录),如果直接回显的话会默认一级下所有目录都选中 代......
  • TreeMap
    TreeMap的使用publicstaticvoidmain(String[]args){ TreeMap<String,Integer>map=newTreeMap<>(); //添加元素 Integerput1=map.put("大文",25); Integerput2=map.put("小文",26); Integerput3=map.put("小王",......
  • 哈夫曼树(Huffman Tree)的基本概念介绍
    哈夫曼树(HuffmanTree)是一种常用的数据结构,用于实现数据压缩和编码。它是由美国计算机科学家DavidA.Huffman于1952年提出的,被广泛应用于通信、压缩算法和信息存储等领域。哈夫曼树主要用于根据字符出现的频率构建最优的前缀编码,以便在压缩数据时能够有效地减少所需的比特数。该......
  • win10打开Sourcetree闪退解决方法
    前言昨天Sourcetree还可以正常使用,今天早上打开后出现下图就闪退了 百度尝试各种操作后找到解决方法,不知是否通用希望有人可以留言告知:删除掉:C:\Users\Administrator\AppData\Local\Atlassian目录下的如图文件,我是装在Administrator下面的,其他人按照实际位置删除 ......