zoukankan      html  css  js  c++  java
  • 【杂题】[CodeForces 1172E] Nauuo and ODT【LCT】【口胡】

    Description

    给出一棵n个节点的树,每个点有一个1~n的颜色

    有m次操作,每次操作修改一个点的颜色
    需要在每次操作后回答树上(n^2)条路径每条路径经过的颜色种类数和。

    (n,m<=400000)

    Solution

    挺有意思的一个套路

    首先我们单独计算每种颜色的贡献,对于每种颜色的点集分开考虑,我们需要计算至少经过了其中一个点的路径条数。
    正难则反,考虑计算一个点都没经过的路径条数,那就是将点集删去后剩余连通块的大小平方和。

    考虑这样一个模型
    对于原本每种颜色有一个黑白两色的树,需要支持在某棵树上颜色翻转,求白连通块的大小平方和。
    黑点总个数为n

    如果只有一棵树,那很好办,直接用个LCT维护白连通块,对于每个点开个虚点连儿子即可。
    但这里白点总个数是(O(n^2))

    原题解给出了这样一个精妙的做法。(翻译一遍题解
    先定一个树根

    我们维护所有的黑连通块,每个黑连通块深度最浅的点的父亲记为这个连通块的顶点,(对于树根我们也开一个0号节点),显然顶点一定是白的。

    LCT的时候,我们将顶点相同的所有节点看做在一个连通块内,事实上他们不一定连通。

    现在对于每个节点都记录两个值,一个是连通块中的子树大小,一个是所有儿子的子树大小的平方和。
    答案显然就是所有顶点的第二个值的和。

    这样颜色反转时,我们只需要讨论这个点是黑点还是白点,黑点的话就cut父亲,显然这个点的信息不变,但这个点会成为顶点,因此更新答案。

    白点的话就link父亲,此时父亲变成顶点,这个点的信息还是没变,只用修改父亲节点的值。

    我们对于每种颜色都按照操作的时间顺序跑一遍,由于总操作数是(O(m))的,因此总共需要用到的点数是(O(n+m))

    我还没去写这道题,感觉具体可以把每种颜色操作一遍,然后回撤到下一种颜色的初始状态,这样总的操作次数仍然是(O(n+m))的。

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

  • 相关阅读:
    024_Python3 filter 函数高级用法
    023_Python3 map 函数高级用法
    022_Python3 lambda函数高级用法
    #整体二分,树状数组#洛谷 3332 [ZJOI2013]K大数查询
    #线段树分治,线性基,并查集#CF938G Shortest Path Queries
    #RMQ,动态开点线段树#CF803G Periodic RMQ Problem
    #二分图匹配#UVA1194 Machine Schedule
    #树状数组套线段树#洛谷 1975 [国家集训队]排队
    #分治,Dijkstra#洛谷 3350 [ZJOI2016]旅行者
    #线段树,离线#CF1000F One Occurrence
  • 原文地址:https://www.cnblogs.com/BAJimH/p/11035454.html
Copyright © 2011-2022 走看看