Cod sursa(job #2096733)

Utilizator AkrielAkriel Akriel Data 29 decembrie 2017 17:44:23
Problema Range minimum query Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 5.09 kb
#include <bits/stdc++.h>

using namespace std;

const int maxWords = 1e4+5,
          maxLetters = 2e5+5,
          sigma = 26,
          dimensions = 2,
          layers = 18;

struct Trie{
    private:
        static int contor;

    public:
        int finished, length, signature;
        Trie *child[sigma];

        Trie (){
            finished = 0;
            length = 0;
            for ( int index = 0; index < sigma; index++ )
                this->child[index] = NULL;
            signature = contor;
            contor++;
        }

        inline void addWord(string word, int &location);
};

int Trie :: contor = 0;

Trie dictionary;

inline void Trie :: addWord(string word, int &location){
    int lengthWord = word.length();
    Trie *position = &dictionary;

    int letter;
    for ( int index = 0; index < lengthWord; index++ ){
        letter = word[index]-'a';

        if ( position->child[letter] == NULL ){
            position->child[letter] = new Trie;
            position->child[letter]->length = position->length+1;
        }

        position = position->child[letter];

        if ( index == lengthWord-1 ){
            position->finished++;
            location = position->signature;
        }
    }
}

ifstream fin ("ratina.in");
ofstream fout ("ratina.out");

vector <int> eulerChart;

int totalWords, totalQuestions,
    depth;

int positions[maxWords],
    eulerPositions[maxWords*2],
    level[maxLetters*2],
    lengthLayer[layers],
    lg2[maxLetters*2];

int rangeMinimumQuery[dimensions][layers][maxLetters];

inline void readVaribles(){
    string word;

    fin >> totalWords >> totalQuestions;
    for ( int index = 0; index < totalWords; index++ ){
        fin >> word;
        dictionary.addWord(word, positions[index]);
    }
}

void depthFirstSearch(Trie *location = &dictionary){
    eulerChart.push_back(location->signature);
    eulerPositions[location->signature] = eulerChart.size();
    level[location->signature] = location->length;

    for ( int index = 0; index < sigma; index++ ){
        if ( location->child[index] ){
            depthFirstSearch(location->child[index]);
            eulerChart.push_back(location->signature);
        }
    }
}

inline void calculateAncenstors(){
    lengthLayer[0] = eulerChart.size();
    depth = lg2[lengthLayer[0]];

    for ( int index = 1; index <= lengthLayer[0]; index++ ){
        rangeMinimumQuery[0][0][index] = level[eulerChart[index-1]];
        rangeMinimumQuery[1][0][index] = eulerChart[index-1];
    }

    for ( int index = 1; index <= depth; index++ ){
        lengthLayer[index] = lengthLayer[index-1] - (1<<(index-1));
    }

    for ( int indexY = 1; indexY <= depth; indexY++ ){
        for ( int indexX = 1; indexX <= lengthLayer[indexY]; indexX++ ){
            if ( rangeMinimumQuery[0][indexY-1][indexX] < rangeMinimumQuery[0][indexY-1][indexX + (1<<(indexY-1))] ){
                rangeMinimumQuery[0][indexY][indexX] = rangeMinimumQuery[0][indexY-1][indexX];
                rangeMinimumQuery[1][indexY][indexX] = rangeMinimumQuery[1][indexY-1][indexX];
            }
            else{
                rangeMinimumQuery[0][indexY][indexX] = rangeMinimumQuery[0][indexY-1][indexX + (1<<(indexY-1))];
                rangeMinimumQuery[1][indexY][indexX] = rangeMinimumQuery[1][indexY-1][indexX + (1<<(indexY-1))];
            }

        }
    }
}

int answerQuestion(int first, int second){
    int positionFirst = eulerPositions[positions[first-1]],
        positionSecond = eulerPositions[positions[second-1]];

    if ( positionFirst > positionSecond )
        swap(positionFirst, positionSecond);

    int lengthPeriod = positionSecond - positionFirst + 1;
    int maxPeriod = 1 << lg2[lengthPeriod];
    int indexY = lg2[maxPeriod];

    if ( rangeMinimumQuery[0][indexY][positionFirst] < rangeMinimumQuery[0][indexY][positionSecond-(1<<indexY)+1])
        return rangeMinimumQuery[0][indexY][positionFirst];
    else
        return rangeMinimumQuery[0][indexY][positionSecond-(1<<indexY)+1];
}

inline void readQuestions(){
    int totalElements,
        first, second,
        answer;
    for ( ; totalQuestions; totalQuestions-- ){
        answer = 1<<30;

        fin >> totalElements >> first;

        for ( int index = 1; index < totalElements; index++ ){
            fin >> second;
            answer = min(answer, answerQuestion(first, second));
            first = second;
        }

        fout << answer << "\n";
    }
}

inline void calculateLog2(){
    for ( int index = 2; index <= eulerChart.size(); index++ )
        lg2[index] = lg2[index >> 1] + 1;
}

inline void debbugingPurposes(){
    cout << "\n";
    for ( int index = 1; index <= totalWords; index++ )
        cout << positions[index-1] << " ";

    cout << "\n";
    for ( int index = 1; index <= totalWords; index++ )
        cout << eulerPositions[index-1] << " ";
    cout << "\n\n!";
}

int main(){
    readVaribles();
    depthFirstSearch();
    calculateLog2();
    calculateAncenstors();
    readQuestions();
}