P3378 【模板】堆
手写堆
#include<bits/stdc++.h>
using namespace std;
int now,tail=0;
int heap[1000001];
void insert(int x)
{
heap[++tail]=x;//从尾端入堆
int now=tail;
while(now>1)//控制不越界,1的位置是根结点
{
int fa=now/2;//父结点下标
if(heap[fa]<=heap[now]) return;//终止条件:父结点值小于等于当前位置的值,无需继续交换
swap(heap[fa],heap[now]);
now=fa;//向上继续
}
}
void de()
{
heap[1]=heap[tail--];//删除根结点,将堆结尾的数交换到根结点
now=1;
while(now*2<=tail)//控制不越界
{
int next=now*2;//next是左儿子,next+1是右儿子
if(next<tail&&heap[next+1]<heap[next]) next++;
//右儿子存在,且其值小于左二子->当前位置与右儿子比较,否则与左儿子比较
if(heap[now]<=heap[next]) return;//终止条件:当前结点值小于等于儿子结点的值,无需继续交换
swap(heap[now],heap[next]);
now=next;//向下继续
}
}
int main()
{
int n,x,y;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
if(x==1)
{
scanf("%d",&y);
insert(y);
}
if(x==2) printf("%d\n",heap[1]);
if(x==3) de();
}
}
STL-优先队列
#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
int n,op,x;
int main()
{
cin>>n;
while(n--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d",&x);
q.push(x);
}
if(op==2) printf("%d\n",q.top());
if(op==3) q.pop();
}
return 0;
}
STL-堆
#include<bits/stdc++.h>
using namespace std;
int heap[1000010];
int n,op,x,k;
int main()
{
cin>>n;
while(n--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d",&x);
heap[++k]=x;
push_heap(heap+1,heap+1+k,greater<int>());
}
if(op==2) printf("%d\n",heap[1]);
if(op==3)
{
pop_heap(heap+1,heap+1+k,greater<int>());
k--;
}
}
return 0;
}
天梯赛L2 关于堆的判断 (25 分)
将一系列给定数字顺序插入一个初始为空的小顶堆H[]
。随后判断一系列相关命题是否为真。命题分下列几种:
x is the root
:x
是根结点;x and y are siblings
:x
和y
是兄弟结点;x is the parent of y
:x
是y
的父结点;x is a child of y
:x
是y
的一个子结点。
输入格式:
每组测试第1行包含2个正整数N
(≤ 1000)和M
(≤ 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间[−10000,10000]内的N
个要被插入一个初始为空的小顶堆的整数。之后M
行,每行给出一个命题。题目保证命题中的结点键值都是存在的。
输出格式:
对输入的每个命题,如果其为真,则在一行中输出T
,否则输出F
。
输入样例:
5 4
46 23 26 24 10
24 is the root
26 and 23 are siblings
46 is the parent of 23
23 is a child of 10
输出样例:
F
T
F
T
#include<bits/stdc++.h>
using namespace std;
int n,m,sheap[1010],k=0;
int find(int x)
{
for(int i=1;i<=k;i++)
if(sheap[i]==x) return i;
return 0;
}
void build_small_heap(int x)
{
sheap[++k]=x;
int now=k;
while(now>1)
{
int fa=now/2;
if(sheap[fa]>sheap[now])
{
swap(sheap[fa],sheap[now]);
now=fa;
}
else break;
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
build_small_heap(x);
}
while(m--)
{
int x;
cin>>x;
string s;
cin>>s;
if(s=="and")
{
int y;
string s1,s2;
cin>>y>>s1>>s2;
if(find(x)/2==find(y)/2)
cout<<"T"<<endl;
else cout<<"F"<<endl;
}
else if(s=="is")
{
string ss;
cin>>ss;
if(ss=="the")
{
string sss;
cin>>sss;
if(sss=="root")
{
if(find(x)==1)
cout<<"T"<<endl;
else cout<<"F"<<endl;
}
else if(sss=="parent")
{
string s1;
int y;
cin>>s1>>y;
if(find(y)/2==find(x))
cout<<"T"<<endl;
else cout<<"F"<<endl;
}
}
else if(ss=="a")
{
string s1,s2;
int y;
cin>>s1>>s2>>y;
if(find(x)/2==find(y))
cout<<"T"<<endl;
else cout<<"F"<<endl;
}
}
}
return 0;
}
UVA1316 Supermarket
- 给定 n 件物品,第 i 件物品有如下信息:
- 卖出去可以得到 p_i 的收益。
- 过期时间为 d_i,过了过期时间就不能再卖出去。
- 卖掉一件物品要用 1天的时间,求最大收益。
- 多组数据,每组数据一行,首先一个整数 n 然后 n 对数 p_i,d_i,以文件终止符结束。
- 0<=n<=1e4,1<=p_i,d_i<=1e4
#include<bits/stdc++.h>
using namespace std;
const int N = 10005;
struct Node
{
int val, day;
} product[N];
bool cmp(Node x,Node y)
{
if(x.day!=y.day) return x.day<y.day;
else return x.val>y.val;
}
int main()
{
int n;
while (cin>>n)
{
memset(product,0,sizeof(product));
priority_queue<int,vector<int>,greater<int> >q;//小根堆
int ans=0;
for(int i=1;i<=n;i++)
scanf("%d %d",&product[i].val,&product[i].day);
sort(product + 1, product + n + 1, cmp);
//排序,把先过期的排在前面
for(int i=1;i<=n;i++)
{
if(q.size()==product[i].day&&product[i].val>q.top())
//前面的“售卖日程”已经排满了,看看是否可以替换 (从堆顶取出最小的与当前值进行比较)
{
q.pop();
q.push(product[i].val);//替换完成
}
else if(q.size()<product[i].day)
//前面的售卖日程没有排满,可以直接安排在前面的一天
q.push(product[i].val);
}
while(q.size())//统计堆中的所有商品总利润
{
int temp=q.top();
q.pop();
ans+=temp;
}
cout<<ans<<endl;
}
return 0;
}