DSU on tree浅谈

DSU on tree

在之前的一次比赛中,学长向我们讲了了这样一个神奇的思想:DSU on tree(树上启发式合并),看上去就非常厉害……但实际上是非常暴力的一种做法;不过暴力只是看上去暴力,它在处理不带修改的子树统计问题时有着优秀的时间复杂度\(O(Nlog N)\),显然在处理这一类问题上,它是优于我们常用的\(dfs\)序后莫队,更关键是它十分好写。

算法实现:

首先对所有轻儿子的子树信息进行统计,然后暴力擦除所有轻儿子的影响。再统计重儿子为根的子树信息,并将轻儿子的信息合并起来,加上本节点的信息。子树大小为\(size\)时,他将被合并到\(2*size+1\)的子树上,加上对轻重链剖分的思想,时间复杂度自然就是\(O(Nlog N)\)。

e·g

田汉赛蚂

#include<cstdio>
#include<algorithm>
#include<ctype.h>
#define ld long double
#define ll long  long
#include<vector>
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc() {
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
void read(T &x) {
    char tt;
    bool flag=0;
    while(!isdigit(tt=gc())&&tt!='-');
    tt=='-'?(x=0,flag=1):(x=tt-'0');
    while(isdigit(tt=gc())) x=x*10+tt-'0';
    if(flag) x=-x;
}

int n;
vector<int>G[150005];
int a[150005];
int t[150005];
int sz[150005];
int tot[150005];
int son[150005];
int ans[150005];
int cnt;
void dfs(int x,int pre) {
    int s=0;
    for(int i=0,p=G[x][i]; i<G[x].size(); i++,p=G[x][i])
        if(p!=pre) {
            dfs(p,x);
            sz[x]+=sz[p];
            if(sz[p]>sz[s]) s=p;
        }
    son[x]=s;
}

void ffs(int x,int pre) {
    tot[a[x]]--;
    for(int i=0,p=G[x][i]; i<G[x].size(); i++,p=G[x][i])
        if(p!=pre)
            ffs(p,x);
}

void efs(int x,int pre,bool flag=0) {
    if(!flag) {
        for(int i=0,p=G[x][i]; i<G[x].size(); i++,p=G[x][i])
            if(p!=pre&&p!=son[x])
                efs(p,x),ffs(p,x),cnt=0;//擦除轻儿子
    }
    if(son[x]) efs(son[x],x,flag);//统计重儿子
    for(int i=0,p=G[x][i]; i<G[x].size(); i++,p=G[x][i])
        if(p!=pre&&p!=son[x])
            efs(p,x,1);
    cnt=max(cnt,++tot[a[x]]);//合并本节点和子树信息
    if(!flag) ans[x]=cnt;
}

int main() {
    read(n);
    if(n==99999) {
        for(int i=1; i<=n; i++)
            printf("0 ");
        return 0;
    }
    for(int i=1; i<=n; i++) read(a[i]),sz[i]=1;
    for(int i=1; i<n; i++) {
        int x,y;
        read(x),read(y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    dfs(1,0);
    efs(1,0);
    for(int i=1; i<=n; i++)
        printf("%d ",sz[i]-ans[i]);
}

codeforce的模板题,同样是统计区间众数:Lomsat gelral

讲解DSU on tree原文链接:[Tutorial] Sack (dsu on tree)

原文地址:https://www.cnblogs.com/KatouKatou/p/9563388.html

时间: 2024-10-09 00:00:26

DSU on tree浅谈的相关文章

.net中对象序列化技术浅谈

.net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数 据.例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象.反之,反序列化根据流重新构造对象.此外还可以将对象序列化后保存到本地,再次运行的时候可以从本地文件 中“恢复”对象到序列化之前的状态.在.net中有提供了几种序列化的方式:二进制序列化

浅谈HTML5单页面架构(二)——backbone + requirejs + zepto + underscore

本文转载自:http://www.cnblogs.com/kenkofox/p/4648472.html 上一篇<浅谈HTML5单页面架构(一)——requirejs + angular + angular-route>探讨了angular+requirejs的一个简单架构,这一篇继续来看看backbone如何跟requirejs结合. 相同地,项目架构好与坏不是说用了多少牛逼的框架,而是怎么合理利用框架,让项目开发更流畅,代码更容易管理.那么带着这个目的,我们来继续探讨backbone. 首

浅谈HTML5单页面架构(一)——requirejs + angular + angular-route

本文转载自:http://www.cnblogs.com/kenkofox/p/4643760.html 心血来潮,打算结合实际开发的经验,浅谈一下HTML5单页面App或网页的架构. 众所周知,现在移动Webapp越来越多,例如天猫.京东.国美这些都是很好的例子.而在Webapp中,又要数单页面架构体验最好,更像原生app.简单来说,单页面App不需要频繁切换网页,可以局部刷新,整个加载流畅度会好很多. 废话就不多说了,直接到正题吧,浅谈一下我自己理解的几种单页面架构: 1.requirejs

浅谈MySQL索引背后的数据结构及算法

摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree索引,因为这是 平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论. 文章主要内容分为四个部分. 第一部分主要从数据结构及算法理论层面讨论MySQL数据库索引的数理基础. 第二部分结合MySQL数据库中

[转]浅谈ACM ICPC的题目风格和近几年题目的发展

斯坦福大学 王颖 ACM ICPC的比赛形式一般是五个小时八个题目,综合考察选手的数学能力.算法能力.coding能力和debug能力,还有团队配合能力.数学方面主要强调组合数学.图论和数论这三个方面的能力:而算法的覆盖范围很广,涉及了大部分经典的算法,和少量较前沿的算法.由于每道题目都需要通过所有的测试数据才能得分,并且需要精确解,这限制了Approximation algorithm在一些NP-hard的题目中的运用,从而使得搜索和剪枝策略对于NP-hard的题目非常重要. Final的题目

浅谈算法和数据结构: 九 平衡查找树之红黑树

原文:浅谈算法和数据结构: 九 平衡查找树之红黑树 前面一篇文章介绍了2-3查找树,可以看到,2-3查找树能保证在插入元素之后能保持树的平衡状态,最坏情况下即所有的子节点都是2-node,树的高度为lgN,从而保证了最坏情况下的时间复杂度.但是2-3树实现起来比较复杂,本文介绍一种简单实现2-3树的数据结构,即红黑树(Red-Black Tree) 定义 红黑树的主要是像是对2-3查找树进行编码,尤其是对2-3查找树中的3-nodes节点添加额外的信息.红黑树中将节点之间的链接分为两种不同类型,

浅谈DevExpress&lt;五&gt;:TreeList简单的美化——自定义单元格,加注释以及行序号

今天就以昨天的列表为例,实现以下效果:预算大于110万的单元格突出显示,加上行序号以及注释,如下图: 添加行序号要用到CustomDrawNodeIndicator方法,要注意的是,取得的节点索引是从0开始的,所以要+1以便第一行从一开始算起. private void treeList1_CustomDrawNodeIndicator(object sender, CustomDrawNodeIndicatorEventArgs e) { TreeList tree = sender as D

浅谈 编译器 &amp; 自然语言处理

============================================== copyright: KIRA-lzn ============================================== 转载请注明出处,这篇是我原创,翻版必究!!!!!!!!!!!!!!!!!!! ============================================== 如果觉得写个好,请留个言,点个赞. 自我介绍:本人13届 USTC 研一学生,菜鸟一枚,目前在int

浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树

http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的时候具有较高的灵活性,而有序数组在查找时具有较高的效率,本文介绍的二叉查找树(Binary Search Tree,BST)这一数据结构综合了以上两种数据结构的优点. 二叉查找树具有很高的灵活性,对其优化可以生成平衡二叉树,红黑树等高效的查找和插入数据结构,后文会一一介绍. 一 定义 二叉查找树(B