В общем виде задача формулируется так:
Нужно создать структуру данных поддерживающую 3 вида операций на массиве:
1) set(i,value) – инициализация i-ого элемента значением value
2) get(i) – получение значение i-ого элемента
3) clear() – обнуление массива.
Каждая операция должна выполняться за O(1).
Первое, что мне пришло в голову было это:
- struct ARRAY {
- vector<int> val;
- vector<int> met;
- int cur;
- int lastClear;
- ARRAY():cur(0), lastClear(0){}
- ARRAY(int size):cur(0), lastClear(0) {
- val.resize(size,0);
- met.resize(size,0);
- }
- void set(int pos, int value) {
- val[pos] = value;
- met[pos] = ++cur;
- }
- int get(int pos) {
- if (met[pos] > lastClear)
- return val[pos];
- return 0;
- }
- void clear() {
- lastClear = ++cur;
- }
- };
* This source code was highlighted with Source Code Highlighter.
Но как это все уж больно по-пацаняче. С более изящным решением меня познакомил Кирилл Цыганов. Оно основано на принципе обратного индексирования:
- const int MAX_REQ = 1000; // максимальное количество запросов set между вызовами clear
- struct ARRAY {
- vector<int> A; // key - индекс; val - значение
- vector<int> S; //key - порядковый номер элемента при добавлении; val - индекс элемента в A
- vector<int> ID;//key - индекс элемента в A; val - порядковый номер элемента при добавлении
- int amount;
- ARRAY():amount(1){}
- ARRAY(int N):amount(1) {
- A.resize(N);
- S.resize(MAX_REQ);
- ID.resize(MAX_REQ);
- }
- void set(int pos, int value) {
- A[pos] = value;
- S[amount] = pos;
- ID[pos] = amount++;
- }
- int get(int pos) {
- if (ID[pos] > amount) // попали в мусор (после clear)
- return 0;
- if (S[ID[pos]] != pos) // обращение к неинициализированному элементу
- return 0;
- return A[S[ID[pos]]];
- }
- void clear() {
- amount = 0;
- }
- };
* This source code was highlighted with Source Code Highlighter.
Комментариев нет:
Отправить комментарий