洛谷 P3378 【模板】堆

题目地址:

$Luogu$:https://www.luogu.org/problemnew/show/P3378

那么我们一看到题目应该就会写这道题了吧。

我们需要支(资)持(辞)三个操作:

1、插入一个数入小根堆(小根队(少先队))

2、输出小根堆的最小值。

3、删除小根堆的最小值。

由于我们知道,小根堆的最小值就是它的根,所以这题就很简单了。

你不用管什么$N<=10^6$,那些都没有关系。

第一个和第三个操作我们需要写两个函数来解决。第二个操作直接输出即可。

第一个函数:插入函数。

void insert(int x)
{
    h[++l]=x;
    up(l);
}

第二个函数:删除函数。

void _delete(int x)
{
    h[x]=h[l--];
    up(x);
    down(x);
}

另附上浮操作$up$以及下沉操作$down$所用的函数。

void up(int x)
{
    while(x>1&&h[x]<h[x>>1])
    {
        swap(h[x], h[x>>1]);
        x>>=1;
    }
}
void down(int x)
{
    int y=x<<1;
    while(y<=l)
    {
        if(y+1<=l&&h[y+1]<h[y]) y++;
        if(h[y]<h[x])
        {
            swap(h[x], h[y]);
            x=y, y=x<<1;
        }
        else break;
    }
}

代码如下:

$code$

#include<bits/stdc++.h>
using namespace std;
const int maxN=1000000+1;
int h[maxN], n, l;
void read(int &), insert(int), up(int), down(int), _delete(int);
int main()
{
	read(n);
	for(int i=1; i<=n; i++)
	{
		int x;
		read(x);
		if(x==1)
		{
			int y;
			read(y);
			insert(y); 
		}
		if(x==2) printf("%d\n", h[1]);
		if(x==3) _delete(1);
		
	}
	return 0;
}
void read(int &x)
{
	x=0;
	char c=getchar();
	while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
}
void up(int x)
{
	while(x>1&&h[x]<h[x>>1])
	{
		swap(h[x], h[x>>1]);
		x>>=1;
	}
}
void down(int x)
{
	int y=x<<1;
	while(y<=l)
	{
		if(y+1<=l&&h[y+1]<h[y]) y++;
		if(h[y]<h[x])
		{
			swap(h[x], h[y]);
			x=y, y=x<<1;
		}
		else break;
	}
}
void insert(int x)
{
	h[++l]=x;
	up(l);
}
void _delete(int x)
{
	h[x]=h[l--];
	up(x);
	down(x);
}

  

猜你喜欢

转载自www.cnblogs.com/Xray-luogu/p/9123212.html