字典树、并查集、堆

一、trie树

const int N =1e5+10;
char str[N];
int son[N][26],cnt[N],idx;  
// 下标是0的点即使根节点也是空节点  
// son[][]存储树中每个节点的子节点
// cnt[]存储以每个节点结尾的单词数量
void insert(char str[])
{
	int p=0; // 根节点 
	for(int i=0;str[i];i++)
	{
		int u= str[i]-'a';
		if(!son[p][u]) son[p][u]= ++idx;
		p = son[p][u];
	}
	cnt[p]++;
}

int query(char str[])
{
	int p=0;
	for(int i=0;str[i];i++)
	{
		int u=str[i]-'a';
		if(!son[p][u]) return 0;  // 如果不存在子节点说明集合中没有该字符串 
		
		p=son[p][u];
	}
	return cnt[p] ;
 } 

二、并查集


const int N = 1e5+10;
int p[N];

int n,m; 
//维护一个size[i]  表示 i集合中有多少个数  只有i是根节点才有意义 
for(int i=1;i<=n;i++)
{
	p[i] = i;
	size[i]=1;
 } 
int find(int x)  // 找祖宗节点+路径压缩 
{
	if(p[x] != x)
		p[x] = find(p[x]);
	return p[x];
}

// 合并 
void union_a(int a,int b)
{
	if(find(a)==find(b))
		continue;
	size[find(b)]+=size[find(a)];
	p[find(a)] = find(b);  让b的祖先 成为 a的祖先的祖先!! 挺不错的哈哈哈哈哈哈哈哈 
} 

三、模拟堆

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
// h[N]存储堆中的值, h[1]是堆顶,x的左儿子是2x, 右儿子是2x + 1
// ph[k]存储第k个插入的点在堆中的位置
// hp[k]存储堆中下标是k的点是第几个插入的
// p是下标的意思 
int h[N],ph[N],hp[N],size;
//h数组存的是堆里面的元素 
//hp 与 ph 的关系      
//hp[i]  ->   ph[k]中的k 
//ph[i] ->    hp[k]中的k 
void heap_swap(int a,int b)
{
	swap(ph[hp[a]],ph[hp[b]]);
	swap(hp[a],hp[b]);
	swap(h[a],h[b]);
}
void down(int u)
{
	int t=u;
	if(2*u <= size && h[2*u] < h[t])	t=2*u;
	if(2*u+1<=size && h[2*u+1]<h[t])	t=2*u+1;
	if(u!=t)
	{
		heap_swap(h[t],h[u]);
		down(t);		
	}	
} 
void up(int u)
{
	while(u/2 && h[u/2]>h[u])
	{
		heap_swap(u/2,u);
		u/=2;
	}
}
// O(n)建堆
for (int i = n / 2; i; i -- ) down(i);
3.1堆排序
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int h[N];
int n,m;
int size;
void down(int x)
{
	int t=x;
	
	if(2*x<=size && h[2*x] < h[t])	
		t= 2*x;	
	if(2*x+1<=size && h[2*x+1]<h[t])
		t=2*x+1;
	
	if(x!=t)
	{
		swap(h[t],h[x]);
		down(t);
	}
} 
void up(int x)
{
	while(x/2 && h[x/2]>h[x])
	{
		swap(h[x/2],h[x]);
		x/=2;	
	}
}
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)	scanf("%d",&h[i]);
	size = n;
	
	for(int i=n/2;i;i--)	down(i);
	while(m--)
	{
		printf("%d ",h[1]);
		h[1] = h[size--];
		down(1);
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值