【算法随笔 Luogu: P1878 舞蹈课】(优先队列 | 断链重连 | 链式)

题目链接icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1878

首先先读题

介绍一下:静态双向单链表的一般构成

以及双链表的断链重连操作

完整代码

#include <cstdio>
#include <cmath>
#include <queue>
#include <array>
#include <bitset>
#include <iostream>

constexpr int __MAX__ { static_cast<int>( 1e5 ) * 2 };
typedef struct {//定义一对节点
 int 	diff; //每一对的水平差距
 int 	first;//第一个人的编号
 int 	second;//第二个人的编号
} node;

std::priority_queue<node> Q;

//记录每个人是否出队(是否有效)
std::bitset<__MAX__ + 1> label {};
//只有label为假,即还没有出队时访问prev和next才有意义

std::array<int, __MAX__ + 1> prev {}; //动态记录每个人的前驱
std::array<int, __MAX__ + 1> next {}; //动态记录每个人的后继


int N {};

//每个人的水平
std::array<int, __MAX__ + 1> value {};
//一共有多少对
int counter {};
//组成的每一对的第一个和第二个人
std::array<int, (__MAX__ >> 1 & 0)> pfirst {};
std::array<int, (__MAX__ >> 1 & 0)> psecond {};

int main(void){
	std::scanf("%d", &N);
	std::string s {};
	s.push_back(std::cin.peek());
	char token {};
	while(~std::scanf("%c", &token)) s += token;
	for(int i {}; i < N; ++i) {
		auto index {i + 1};
		std::scanf("%d", &value[index]);
		next[index] = index + 1;
		prev[index] = index - 1;
		if(s[index - 1] == s[index]) continue;
		Q.emplace(std::abs(value[index] - value[index - 1]), i - 1, i);
	}
	while(!Q.empty()) {
		auto [diff, first, second] = Q.top();
		Q.pop();
		if(! first || ! second) continue;
		if(label[first] || label[second]) continue;
		next[prev[first]] = next[second];
		prev[next[second]] = prev[first];
		pfirst[counter] = first;
		psecond[counter] = second;
		++ counter;
		if(label[prev[first]] || label[next[second]]) continue;
		if(s[prev[first]] == s[next[second]]) continue;
		Q.emplace(std::abs(value[prev[first]] - value[next[second]]), prev[first], next[second]);
	}
	std::printf("%d\n", counter);
	for(int i {}; i < counter; ++i)
		std::printf("%d %d\n", pfirst[i], psecond[i]);
	return 0;
}


  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XNB's Not a Beginner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值