zoukankan      html  css  js  c++  java
  • 简单启发式合并

    概述:有 N 个集合, 每个集合大小为 1, 只有合并两个集合的操作, 若每次合并两个集合把小集合的元素拿出来插入到大集合里, 那么对于小集合里的元素, 所在集合的大小翻倍了。

    所以所有元素被插入的次数是 (O(log N)) 的。


    P3302

    对于森林的每棵树, 用倍增数组维护 LCA, 维护到根的可持久化线段树。

    于是查询的时候直接查, 连边的时候重构较小的那棵树。

    代码不难。

    P5290

    好好读题分析的时候就不会痛苦了。

    很多连续动作用 for 语句表示会很好看。

    比如:

    for (cnt = 0; q[y].size(); q[x].pop(), q[y].pop()) {
     o[cnt++] = std :: max(q[x].top(), q[y].top());
    }
    

    记录

    P3224

    用维护整数集合的东西启发式合并即可。

    复习一下 treap。

    一个 update siz 的小函数少加了一个 1 就调了这么长时间啊……

    记录

    struct node {
    	int siz, val, rnd, c[2];
    	node() {}
    	node(int s, int v) : siz(s), val(v) {
    		rnd = rand();
    		c[0] = c[1] = 0;
    	}
    } t[N];
    int tot, root;
    
    inline void upd (int me) {
    	t[me].siz = t[t[me].c[0]].siz + t[t[me].c[1]].siz + 1;
    }
    
    void ro (int & me, int dir) {
     int y = t[me].dir;
     t[me].c[dir] = t[y].c[dir ^ 1], t[y].c[dir ^ 1] = me;
     upd(me), upd(y);
     me = y;
    }
    
    void ins (int x, int & me) {
     if (!me) { t[me] = node(1, x); return; }
     ++ t[me].siz;
     int dir = x > t[me].val;
     ins (x, t[me].c[dir]);
     if (t[me].c[dir][t].rnd > t[me].rnd) ro (me, dir);
    }
    
    void del (int x, int & me) {
     if (!me) return ;
     if (t[me].val != x) {
      --t[me].siz;
      del (x, t[me].c[x > t[me].val]);
     } else {
      if (!t[me].c[0] || !t[me].c[1]) me = t[me].c[0] | t[me].c[1];
      else {
       int dir = t[t[me].c[1]].rnd > t[t[me].c[0]].rnd;
       ro (me, dir);
       --t[me].siz;
       del (x, t[me].c[dir ^ 1]);
      }
     }
    }
    

    P3402【可持久化并查集】

    记录来看我清晰直观的代码!

    CF600E【树上启发式合并】

    直接用这题介绍了, 算法过程:

    1. 计算所有轻儿子贡献,并撤回所有插入
    2. 计算重儿子贡献,不对数据结构做任何操作
    3. 将轻儿子全部插入数据结构
    4. 回答当前子树询问,回溯

    一个点作为轻儿子子树的点的次数是 (O(log N)) 级别的。

    记录

    可以用 【DSU ON TREE】这种 coding style, 即依据 dfs 序的子树内连续的性质通过遍历 dfs 序来遍历子树中的结点。 会让生活变得轻松

    CF741D

    好长的题面耶。

    刚开始读成了排序而不是重新排列?????????

    由于启发式合并也有一个一个插入轻儿子的过程, 所以统计这个东西就很轻松了。

    记录

    不小心加了点蛇足,不过影响不大。

  • 相关阅读:
    [基础规范]JavaBeans规范
    leetcode 114.Flatten Binary Tree to Linked List (将二叉树转换链表) 解题思路和方法
    sql 分组取每组的前n条或每组的n%(百分之n)的数据
    D3js-API介绍【中】
    微信公众平台开发 一 账号类别与申请
    Apple Swift编程语言新手教程
    iOS中xib与storyboard原理,与Android界面布局的异同
    Scala入门到精通——第十五节 Case Class与模式匹配(二)
    使用IDA破解TraceMe.exe
    21行python代码实现拼写检查器
  • 原文地址:https://www.cnblogs.com/tztqwq/p/14589600.html
Copyright © 2011-2022 走看看