【JAVA】求数组前K个数中固定位置元素之和Pro20210524 (优先级队列 / IndexTree)

这是一个关于计算满意度分数之和的问题,当接收的满意度为Y的倍数时,需要调查X/Y位置的满意度。文章介绍了两种解决方案:优先级队列和IndexTree,分别详细阐述了每种方法的思路和操作流程,通过实例解释了如何在不同情况下处理满意度分数的增删和计算。
摘要由CSDN通过智能技术生成

【JAVA】求数组前K个数中固定位置元素之和Pro20210524

题目

用户用餐后会在外卖应用上对食物的满意度进行评价。(满意度分数始终大于0)
研究满意度的专家称,当把满意度分数按照从小到大的顺序排列时,某个(X/Y)位置的满意度非常重要。因此作为管理满意度的负责人丽雅,她想逐个接收分数后进行处理。
每当接收的满意度为Y的倍数时,会调查X/Y位置的满意度并进行记录。(如果X=3,Y=4的情况,满意度有4个时取第三个分数,有八个时取第六个分数。)
然而,有时候用户也会删除他们的满意度分数。这种情况,为了方便会把该满意度分数接收为负数,然后删除该分数。(确定删除只会发生在已存在的分数上。)然而删除后,数据个数重新变成Y的倍数时,也仍然需要调查满意度分数并进行记录。

让我们思考一下 X=3,Y=4,并且按照 7、5、3、1、-1、7、7、5、6、1、-7、1 的顺序接收12个满意度分数的情况。
在这里插入图片描述

首先按照7、5、3、1的顺序输入时,输入的数据个数满足Y的倍数,所以按升序排列时,会成为[图1],X/Y位置的满意度分数是5。
在这里插入图片描述

接着输入了-1时,会如上[图2]一样,前面的1会被删除(请注意,负数值本身不是输入值,而是要删除的值), 然后输入7,会成为[图3]。此时,数据个数重新会变成Y的倍数,X/Y位置的满意度值为7。
在这里插入图片描述

然后输入7、5、6、1时,数据会成为Y的倍数,会有8个值按从小到大排序,此时跟[图4]一样,这时X/Y位置的值为7。
在这里插入图片描述

最后输入-7、1时,跟上述的条件一样,会删除一个跟-7的绝对值相同的7,然后添加1后,数据个数又会变成Y的倍数,成为[图 5]。此时的X/Y位置的值为6,所以符合条件的位置上所在的满意度分数之和为25(5+7+7+6)。

求出丽雅记录的满意度之和。

[限制条件]
1.输入的满意度分数的个数N为介于4到300,000之间的整数。
2.满意度分数为介于-1,000,000,000 到 1,000,000,000 之间的整数,分数为整数时,表示用户输入的满意度,分数为负数时,表示用户删除的满意度。不会给出0。
3.删除时,存在多个相同的满意度绝对值时,只删除其中一个满意度。
4.不会删除不存在的满意度。
5.X和Y是介于1到N的整数,且必须为互质数。
6.X小于Y。

[输入]
首先给出测试用例数量T,接着给出T种测试用例。每个测试用例的第一行给出数据个数N,以及空格区分给出表示比率的X,Y。第二行空格区分给出N个数字。

[输出]
每个测试用例输出一行。各测试用例输出#x(x是测试用例的编号,从1开始),加一个空格,输出丽雅调查的满意度之和。

[输入输出 示例]
(输入)
3
12 3 4
7 5 3 1 -1 7 7 5 6 1 -7 1
6 2 3
3 -3 2 4 4 1
9 2 3
7 2 6 2 7 7 3 3 7
(输出)
#1 25
#2 4
#3 20

方法一:优先级队列

思路:
维护两个优先级队列,一个降序,一个升序;
确保在有效元素的个数P是Y的倍数时,前 (P / Y) * X 个在升序的PQ中,后 P - (P / Y) * X 个在降序的PQ中;
添加数字时,优先往降序的PQ中添加(即:当 P / Y < X 时,往降序的PQ中添加;当 P / Y >= X 时,往升序的PQ中添加);
出现要删除的数D时,确认这个数在哪个PQ中(与降序PQ的有效元素中的最大值M比较,当 D <= M时,D在降序PQ中,反之则在升序PQ中),优先从降序的PQ中删除(不是真删除,需要一个集合,记录某个元素删除的次数);
当效元素的个数P是Y的倍数时,从降序PQ中获取最大有效元素(若获取的最大值,被删除的次数大于0时,重新获取,并将该元素的删除次数减一)累加为SUM;
SUM即为所求。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.HashMap;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Solution {
   
	static HashMap<Integer, Integer> hm;

	public static void main(String[] args) throws IOException {
   
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		int T = Integer.parseInt(st.nextToken());

		for (int t = 1; t <= T; t++) {
   
			st = new StringTokenizer(br.readLine());
			int N = Integer.parseInt(st.nextToken());
			int X = Integer.parseInt(st.nextToken());
			int Y = Integer.parseInt(st.nextToken());

			PriorityQueue<Integer> pqL =
好的,下面是用Java数组实现优先级队列的示例代码: ```java public class PriorityQueue { private int[] heap; private int maxSize; private int size; public PriorityQueue(int maxSize) { this.maxSize = maxSize; heap = new int[maxSize]; size = 0; } public boolean isEmpty() { return size == 0; } public boolean isFull() { return size == maxSize; } public void enqueue(int item) { if (isFull()) { throw new RuntimeException("Priority queue is full"); } heap[size] = item; heapifyUp(size++); } public int dequeue() { if (isEmpty()) { throw new RuntimeException("Priority queue is empty"); } int item = heap[0]; heap[0] = heap[--size]; heapifyDown(0); return item; } private void heapifyUp(int index) { int parent = (index - 1) / 2; while (index > 0 && heap[index] > heap[parent]) { swap(index, parent); index = parent; parent = (index - 1) / 2; } } private void heapifyDown(int index) { int left = 2 * index + 1; int right = 2 * index + 2; int largest = index; if (left < size && heap[left] > heap[largest]) { largest = left; } if (right < size && heap[right] > heap[largest]) { largest = right; } if (largest != index) { swap(index, largest); heapifyDown(largest); } } private void swap(int i, int j) { int temp = heap[i]; heap[i] = heap[j]; heap[j] = temp; } } ``` 上述代码定义了一个 `PriorityQueue` 类,它有以下方法: - `isEmpty()`:判断队列是否为空,返回布尔值。 - `isFull()`:判断队列是否已满,返回布尔值。 - `enqueue(int item)`:将一个元素插入队列。 - `dequeue()`:从队列删除元素并返回该元素的值。 在这个示例,我们使用一个数组来存储队列元素。我们使用 `heapifyUp()` 和 `heapifyDown()` 方法来维护堆的性质,确保队列元素按照优先级进行排序。在 `enqueue()` 方法,我们将新元素插入到队列的末尾,然后将它上移以保持堆的性质。在 `dequeue()` 方法,我们删除队列的根节点(即具有最高优先级的元素),将末尾元素移动到根节点处,然后将其下移以保持堆的性质。 请注意,这个示例优先级队列是最大堆,即具有最高优先级的元素总是位于队列的面。如果您需要实现最小堆,只需要将 `heapifyUp()` 和 `heapifyDown()` 方法的比较运算符反转即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值