堆 AcWing 839. 模拟堆
维护一个集合,初始时集合为空,支持如下几种操作:
I x,插入一个数 x;
PM,输出当前集合中的最小值;
DM,删除当前集合中的最小值(数据保证此时的最小值唯一);
D k,删除第 k 个插入的数;
C k x,修改第 k 个插入的数,将其变为 x;
现在要进行 N 次操作,对于所有第 2 个操作,输出当前集合的最小值。
输入格式
第一行包含整数 N。
接下来 N 行,每行包含一个操作指令,操作指令为 I x,PM,DM,D k 或 C k x 中的一种。
输出格式
对于每个输出指令 PM,输出一个结果,表示当前集合中的最小值。
每个结果占一行。
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int N=100010;
int h[N],hp[N],ph[N],size;
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 (u*2<=size && h[u*2]<h[t]) t=u*2;
if (u*2+1<=size && h[u*2+1]<h[t]) t=u*2+1;
if (u!=t)
{
heap_swap (u,t);
down (t);
}
}
void up (int u)
{
while (u/2 && h[u/2]>h[u])
{
heap_swap (u/2,u);
u/=2;
}
}
int main()
{
int n,m=0;
scanf ("%d",&n);
while (n--)
{
char op[10];
int k,x;
scanf ("%s",op);
if (!strcmp(op,"I"))
{
scanf ("%d",&x);
size++;
m++;
ph[m]=size,hp[size]=m;
h[size]=x;
up(size);
}
else if (!strcmp(op,"PM")) printf ("%d\n",h[1]);
else if (!strcmp(op,"DM"))
{
heap_swap(1,size);
size--;
down(1);
}
else if (!strcmp(op,"D"))
{
scanf("%d",&k);
k=ph[k];
heap_swap(k,size);
size--;
down(k),up(k);
}
else
{
scanf ("%d%d",&k,&x);
k=ph[k];
h[k]=x;
down(k),up(k);
}
}
return 0;
}
一般哈希 AcWing 840. 模拟散列表
维护一个集合,支持如下几种操作:
I x,插入一个整数 x;
Q x,询问整数 x 是否在集合中出现过;
现在要进行 N 次操作,对于每个询问操作输出对应的结果。
输入格式
第一行包含整数 N ,表示操作数量。
接下来 N 行,每行包含一个操作指令,操作指令为 I x,Q x 中的一种。
输出格式
对于每个询问指令 Q x,输出一个询问结果,如果 x 在集合中出现过,则输出 Yes,否则输出 No。
每个结果占一行。
// 模拟散队列 拉链法 哈希表
#include<iostream>
#include<cstring>
using namespace std;
const int N=100003;
int h[N],e[N],ne[N],idx;
void insert (int x)
{
int k=(x%N+N)%N;
e[idx]=x;
ne[idx]=h[k];
h[k]=idx++;
}
bool find (int x)
{
int k=(x%N+N)%N;
for (int i=h[k];i!=-1;i=ne[i])
if (e[i]==x)
return true;
return false;
}
int main()
{
int n;
scanf ("%d",&n);
memset(h,-1,sizeof h);
while (n--)
{
char op[2];
int x;
scanf ("%s%d",op,&x);
if (*op=='I') insert (x);
else
{
if (find (x)) puts ("Yes");
else puts ("No");
}
}
return 0;
}
插入函数 insert
确定哈希桶位置:首先通过 int k=(x%N+N)%N; 这行代码计算要插入元素 x 在哈希表中的位置 k。这里先对 x 取余 N,然后再加上 N 后再次取余 N,是为了确保得到的索引值在 0 到 N - 1 的范围内,处理可能出现的负数取余情况(在 C++ 中,负数取余的结果可能不符合预期,这样处理能保证得到正确的正整数索引)。
构建链表插入元素:接着 e[idx]=x; 将当前要插入的元素值 x 存储到 e 数组中以 idx 为索引的位置。ne[idx]=h[k]; 这行代码把当前位置 idx 的下一个节点指针设置为原来哈希桶 k 对应的链表头指针(也就是 h[k] 的值,如果原来该哈希桶没有元素,h[k] 为 -1),相当于将新元素插入到链表头部。最后 h[k]=idx++; 把当前插入元素的索引 idx 赋值给 h[k],使得 h[k] 指向新插入元素所在的链表节点,然后将 idx 的值加 1,为下一次插入元素准备好新的索引。
查找函数 find
确定哈希桶位置:同样先通过 int k=(x%N+N)%N; 计算出元素 x 在哈希表中对应的哈希桶位置 k。
遍历链表查找元素:然后通过一个 for 循环,从哈希桶 k 对应的链表头指针 h[k] 开始遍历链表(只要当前节点指针 i 不为 -1,就继续循环,通过 i=ne[i] 不断更新指针指向下一个节点),在遍历过程中,比较链表中每个节点存储的元素值(通过 e[i] 获取)与要查找的元素 x 是否相等,如果找到相等的元素,就返回 true,表示元素在哈希表中存在;如果遍历完整个链表都没有找到相等的元素,就返回 false,表示元素不在哈希表中。
1735

被折叠的 条评论
为什么被折叠?



