寻找数列最小元素
【问题描述】
给定一个长度为n的数列,现声明两种操作。
第一种操作add,将数列的第i个元素的值增加x
第二种操作query,询问此时数列中最小的元素是哪个。
【输入形式】
第一行为一正整数n(<=500000)表示数列长度。
第二行为n个整数,表示数列初始元素。
第三行为一个正整数q(<=1000000),表示操作数。
接下来q行,每行描述一种操作:
add i x
表示数列第i(1<=i<=n)个元素增加x(-1000<=x<=1000)。
query
输出此时数列中最小元素所在位置,以及最小值。多个最小值输出下标最小的那个。
【输出形式】
对于每个query操作,输出一行,包含两个数字,第一个数字为最小值所在下标,第二个数字表示最小值。
【样例输入】
5
1 2 3 4 5
5
query
add 1 2
query
add 2 2
query
【样例输出】
1 1
2 2
1 3
【样例说明】
第一次query时数列为1,2,3,4,5,输出1,1
第二次query时数列为3,2,3,4,5,输出2,2
第三次query时数列为3,4,3,4,5,输出1,3
#include <iostream>
#include <string>
using namespace std;
class elem {
public:
int index;
int num;
elem(int i = 0, int n = 0):index(i), num(n){}
bool operator<(const elem& e) const{
if (this->num == e.num)
return this->index < e.index;
return this->num < e.num;
}
bool operator>(const elem& e) const{
if (this->num == e.num)
return this->index > e.index;
return this->num > e.num;
}
};
class priorityQueue {
public:
// priorityQueue(int capacity = 100);
priorityQueue(const elem data[], int size);
~priorityQueue();
// bool isEmpty() const;
// void enQueue(const elem & x);
// elem deQueue();
elem getHead() const;
// int size() const { return currentSize; }
void addIndexElem(int index, int num);
void printArr();
void printArrIndex();
private:
int currentSize;
elem *array;
int *arr_index; // map original index to array index
int maxSize;
void doubleSpace() ;
void buildHeap() ;
void percolateDown(int hole);
void percolateUp(int hole);
};
//priorityQueue::priorityQueue(int capacity)
//{
// array = new elem[capacity];
// maxSize = capacity;
// currentSize = 0;
//}
priorityQueue::priorityQueue(const elem* items, int size) :maxSize(size + 10), currentSize(size){
array = new elem[maxSize];
arr_index = new int[size];
for (int i = 0; i < currentSize; ++i){
array[i + 1] = items[i];
arr_index[i] = i + 1;
}
buildHeap();
}
priorityQueue::~priorityQueue(){
delete [] array;
delete [] arr_index;
}
//bool priorityQueue::isEmpty()const
//{
// return currentSize == 0;
//}
elem priorityQueue::getHead()const{
return array[1];
}
//void priorityQueue::enQueue(const elem& x)
//{
// if (currentSize == maxSize - 1) doubleSpace();
// int hole = ++currentSize;
// for (; hole > 1 && x < array[hole / 2]; hole /= 2)
// array[hole] = array[hole / 2];
// array[hole] = x;
//}
//void priorityQueue::doubleSpace()
//{
// elem* tmp = array;
// maxSize *= 2;
// array = new elem[maxSize];
// for (int i = 0; i <= currentSize; ++i)
// array[i] = tmp[i];
// delete[]tmp;
//}
//elem priorityQueue::deQueue()
//{
// elem minItem;
// minItem = array[1];
// array[1] = array[currentSize--];
// percolateDown(1);
// return minItem;
//}
void priorityQueue::percolateDown(int hole){
int child;
elem tmp = array[hole];
for (; hole * 2 <= currentSize; hole = child)
{
child = hole * 2;
if (child != currentSize && array[child + 1] < array[child])
child++;
if (array[child] < tmp) {
array[hole] = array[child];
arr_index[array[child].index] = hole;
}
else break;
}
array[hole] = tmp;
arr_index[tmp.index] = hole;
}
void priorityQueue::percolateUp(int hole){
int parent;
elem tmp = array[hole];
while (hole > 1) {
parent = hole / 2;
if (array[parent] > tmp) {
array[hole] = array[parent];
arr_index[array[parent].index] = hole;
hole = parent;
}
else break;
}
array[hole] = tmp;
arr_index[tmp.index] = hole;
}
void priorityQueue::printArr(){
for (int i = 1; i <= currentSize; i++) {
cout << "array["<< i << "] = "
<< '(' << array[i].index << ", " << array[i].num << ')'<< endl;
}
}
void priorityQueue::printArrIndex(){
for (int i = 0; i < currentSize; i++) {
cout << "arr_index["<< i << "] = " << arr_index[i] << endl;
}
}
void priorityQueue::buildHeap(){
for (int i = currentSize / 2; i > 0; i--)
percolateDown(i);
}
void priorityQueue::addIndexElem(int index, int num){
if (num == 0) return;
int i = arr_index[index];
array[i].num += num;
if (num > 0)
percolateDown(i);
else if (num < 0)
percolateUp(i);
}
int main()
{
int n, num;
cin >> n;
elem* a = new elem[n];
for (int i = 0; i < n; i++) {
scanf("%d", &num);
a[i].index = i;
a[i].num = num;
}
priorityQueue q(a, n);
cin >> num;
while (num--) {
string s;
cin >> s;
if (s == "query"){
elem min_elem = q.getHead();
printf("%d %d\n", min_elem.index + 1, min_elem.num);
}
else if (s == "add") {
int index;
int num;
scanf("%d%d", &index, &num);
q.addIndexElem(index - 1, num);
}
// q.printArr();
// q.printArrIndex();
}
return 0;
}