洛谷题单【数据结构2-1】二叉堆与 ST 表

P3865 【模板】ST 表

思路

关于ST表的讲解非常好的知乎文章
Pecco的知乎文章

实现

#include <bits/stdc++.h>
#define MAXN 100005
using namespace std;
int read()
{
    int ans = 0;
    char c = getchar();
    while (!isdigit(c))
        c = getchar();
    while (isdigit(c))
    {
        ans = ans * 10 + c - '0';
        c = getchar();
    }
    return ans;
}
int Log2[MAXN], Max[MAXN][17];
int main()
{
    int n = read(), m = read();
    for (int i = 1; i <= n; ++i)
    {
        int x = read();
        Max[i][0] = x;
    }
    for (int i = 2; i <= n; ++i)
        Log2[i] = Log2[i / 2] + 1;
    for (int i = 1; i <= 16; ++i)
        for (int j = 1; j + (1 << i) - 1 <= n; ++j)
        {
            Max[j][i] = max(Max[j][i - 1], Max[j + (1 << (i - 1))][i - 1]);
        }
    for (int i = 0; i < m; ++i)
    {
        int l = read(), r = read();
        int s = Log2[r - l + 1];
        int ma = max(Max[l][s], Max[r - (1 << s) + 1][s]);
        printf("%d\n", ma);
    }
    return 0;
}

P1878 舞蹈课

思路

简单的模拟+二叉堆(priority_queue

实现

#include <bits/stdc++.h>
#define MAXN 200005
using namespace std;
struct node
{
	int x,y;
	int sub;
	friend bool operator < (node a,node b)
	{
		if(a.sub == b.sub) return a.x>b.x;
		else return a.sub > b.sub;
	}
};
pair<int,int> ans[MAXN];
int cnt;
priority_queue<node,vector<node> > q;
int n;
int a[MAXN];
bool vis[MAXN];
bool flag[MAXN];
int main()
{
	node t;
	string s;
	scanf("%d",&n);
	cin>>s;
	for(int i=0;i<n;i++)
	{
		if(s[i]=='G') flag[i+1] = 1;
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	for(int i=1;i<n;i++)
	{
		if(flag[i]!=flag[i+1])
		{
			t.x = i;
			t.y = i+1;
			t.sub = abs(a[i]-a[i+1]);
			
			q.push(t); 
		}
	}
	while(!q.empty())
	{
		int x = q.top().x;
		int y = q.top().y;
		q.pop();
		if(vis[x] || vis[y]) continue;
		vis[x] = 1;
		vis[y] = 1;
		
		ans[cnt].first = x;
		ans[cnt].second = y;
		++cnt;
		
		while(x>0 && vis[x]) --x;
		while(y<=n && vis[y]) ++y;
		if(x>0 && y<=n && flag[x]!=flag[y])
		{
			t.x = x;
			t.y = y;
			t.sub = abs(a[x]-a[y]);
			
			q.push(t); 		
		}
	}
	printf("%d\n",cnt);
	for(int i=0;i<cnt;i++)
	{
		printf("%d %d\n",ans[i].first,ans[i].second);
	}
	return 0;
}

P1801 黑匣子

思路

对顶堆是由两个堆(大根堆和小根堆)组成的特殊数据结构

  • add操作:大根堆中的元素个数小于i时直接加入大根堆,大于i时将大根堆的根加入小根堆,pop掉根,就产生了空位,可以加入一个元素。
  • get操作:大根堆的根即为第i小的元素

P1168 中位数 和这道题类似,也是使用对顶堆

实现

#include <bits/stdc++.h>
#define MAXN 200005
using namespace std;
int a[MAXN];
priority_queue<int>A;
priority_queue<int,vector<int>,greater<int>>B;
int main(){    
	int n,m;
	int r=1,q;
	scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
    for(int i=1;i<=m;i++)
	{
        scanf("%d",&q);
        for(int j=r;j<=q;j++)
		{
            A.push(a[j]);
            if(A.size()==i)B.push(A.top()),A.pop();
        }
        r=q+1;
        printf("%d\n",B.top());
        A.push(B.top()),B.pop();
    }
    return 0;
}

欢迎指正-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值