• Trie树合并


    因为省选 (Day2T2) 来学习 (01 trie) 合并……

    首先和线段树合并还有左偏树的 (merge) 一样的,就是一个 (merge) 函数

    inline int merge(int x,int y)
    {
    	if(!x||!y) return x+y;
    	int p=++tot;
    	for(int i=0;i<=25;++i) ch[p][i]=merge(ch[x][i],ch[y][i]);
    	return p;
    }
    

    然后就实现了 (trie) 树的合并(啊不是 (01 trie)

    然后是一个应用题:

    (CF778C)

    可以在一棵 (trie) 树上面删除一层的边,剩下的子树如果可以就像普通 (trie) 一样合并

    求删掉哪一层剩下的点最少


    这题的贡献法不太好想

    删掉哪层剩下的点最少,那就考虑删掉的点最多的一层

    考虑一下合并的过程我们会新开节点,如果新开一个相当于有一个被删掉了

    然后就可以从上到下 (dfs) 处理这个过程了


    接着是省选题:

    P6623 [省选联考 2020 A 卷] 树

    其实不一定是 (01 trie) 合并做?

    简述题意:

    实现一个支持区间加 (1) ,区间异或和的数据结构、


    其实难点在区间加一

    然后如果在 (trie) 上面做就是交换左右儿子

    (正好学了个板子……)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=54e4;
    	int n,ans,res[N],v[N];
    	vector<int> g[N];
    	int tot,cnt[N*20],val[N*20],dep[N*20],ls[N*20],rs[N*20],rt[N],fa[N];
    	inline void push_up(int x){val[x]=val[ls[x]]^val[rs[x]]^((cnt[rs[x]]&1)<<dep[x]); return ;}
    	inline int merge(int x,int y)
    	{
    		if(!x||!y) return x+y;
    		cnt[x]+=cnt[y]; 
    		ls[x]=merge(ls[x],ls[y]); rs[x]=merge(rs[x],rs[y]);
    		push_up(x);
    		return x;
    	}
    	inline void add(int p)
    	{
    		if(!p||dep[p]>20) return ;
    		add(rs[p]); swap(rs[p],ls[p]);
    		push_up(p);
    	}
    	inline void insert(int &p,int val,int d)
    	{
    		if(!p) p=++tot,dep[p]=d;
    		++cnt[p]; if(d>20) return ;
    		if((val>>d)&1) insert(rs[p],val,d+1);
    		else insert(ls[p],val,d+1);
     		return push_up(p);
    	}
    	inline void dfs(int x)
    	{
    		int siz=g[x].size();
    		for(int i=0;i<siz;++i) dfs(g[x][i]),rt[x]=merge(rt[x],rt[g[x][i]]);
    		add(rt[x]); insert(rt[x],v[x],0);
    		res[x]=val[rt[x]];
    		return ;
    	}
    	signed main()
    	{
    		n=read(); for(int i=1;i<=n;++i) v[i]=read();
    		for(int i=2;i<=n;++i) fa[i]=read(),g[fa[i]].push_back(i); dfs(1);
    		for(int i=1;i<=n;++i) ans+=res[i]; printf("%lld
    ",ans); 
    		return 0;
    	}
    } 
    signed main(){return yspm::main();}
    
  • 相关阅读:
    LeetCode--Array--Two sum (Easy)
    LeetCode--Unique Email Addresses & Hamming Distance (Easy)
    LeetCode--Squares of a Sorted Array && Robot Return to Origin (Easy)
    LeetCode--Sort Array By Parity && N-Repeated Element in Size 2N Array (Easy)
    LeetCode 11月第1周题目汇总
    LeetCode 十月份题目汇总
    【每天一题】LeetCode 172. 阶乘后的零
    【每天一题】LeetCode 121. 买卖股票的最佳时机
    【每天一题】LeetCode 0107. 自底向上层遍历二叉树
    【每天一题】LeetCode 0067. 二进制求和
  • 原文地址:https://www.cnblogs.com/yspm/p/13193376.html
Copyright © 2020-2023  润新知