• dsu on tree


    推荐GsjzTle的博客

    (dsu on tree),即树上启发式合并。它要满足:

    • 只有询问,且是离线
    • 只涉及到子树(或者可以把问题转化为子树上操作)
    • 子树之间不会互相干扰

    它和莫队的思想其实有一点像,都是“优雅的暴力”

    具体的实现过程:

    • 对于树上一个节点(x),先处理轻子树的答案,统计完只影响到(x),不向上保留
    • 再处理重子树答案,统计完不仅会影响到(x),还要向上保留
    • 回溯时,算出(x)轻子树的答案((calc(1)))。如果不能保留,则删掉贡献((calc(-1)))。((calc())函数暴力算)

    这样做的时间复杂度是对的,因为一个点到根路径上不超过(log n)条轻边

    具体代码:

    void dfs(int x, int f)
    {
    	sz[x] = 1; int mx = 0; 
    	for (int i = hd[x]; i; i = nxt[i])
    	{
    		int y = to[i];
    		if (y == f) continue;
    		dep[y] = dep[x] + 1;
    		dfs(y, x), sz[x] += sz[y];
    		if (sz[y] > mx) mx = sz[y], ms[x] = y; // 重儿子
    	}
    	return;
    }
    
    void calc(int x, int f, int o)
    {
    	if (o == 1) // do something (统计子树内答案)
    	else // do something (消除影响)
    	for (int i = hd[x]; i; i = nxt[i])
    	{
    		int y = to[i];
    		if (y == f || y == nms) continue;
    		calc(y, x, o);
    	}
    	return;
    }
    
    void dsu(int x, int f, int o)
    {
    	for (int i = hd[x]; i; i = nxt[i])
    	{
    		int y = to[i];
    		if (y == f || y == ms[x]) continue;
    		dsu(y, x, -1); // 轻子树
    	}
    	if (ms[x]) dsu(ms[x], x, 1), nms = ms[x]; // 重子树
    	calc(x, f, 1), nms = 0;
      	ans[x] = ... // 更新答案
    	if (o == -1) calc(x, f, -1);
    	return;
    }
    
  • 相关阅读:
    window
    pages
    百度小程序 配置 app.json 文件
    JavaScript Cookie
    jQuery ajax
    jQuery ajax
    jQuery ajax
    jQuery
    jQuery
    jQuery
  • 原文地址:https://www.cnblogs.com/andysj/p/14627895.html
Copyright © 2020-2023  润新知