Cod sursa(job #1326427)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 25 ianuarie 2015 13:50:49
Problema Hashuri Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 4.2 kb
#include <bits/stdc++.h>

using namespace std;

///---------------------------------

const int BS = ( 1 << 20 );
char buffer[BS];
int position = BS;

inline char getChar()
{
    if ( position == BS )
    {
        position = 0;
        fread( buffer, BS, 1, stdin );
    }

    return buffer[ position++ ];
}

inline int getNr()
{
    int a = 0;
    char ch;

    do
    {
        ch = getChar();

    } while ( !isdigit( ch ) );

    do
    {
        a = a * 10 + ch - '0';
        ch = getChar();

    } while ( isdigit( ch ) );

    return a;
}

///--------------------------------------

const int INF = ( 1U << 31 ) - 1;
const int MAX_LEVEL = 20;
const int SIZE_SKIPLIST = 5000000;

int SL[SIZE_SKIPLIST], width[SIZE_SKIPLIST];
int levelNode[MAX_LEVEL], jumped[MAX_LEVEL];
int pointer, maxLevel;

double getMemory()
{
    return 2.0 * (double)sizeof( SL ) / 1024.0 / 1024.0;
}

void initSkiplist()
{
    srand( time( NULL ) );

    SL[0] = -INF;

    for ( int i = 0; i < MAX_LEVEL; ++i )
        SL[i + 1] = MAX_LEVEL + 1;

    SL[MAX_LEVEL + 1] = INF;

    pointer = MAX_LEVEL + 2;
    maxLevel = 1;
}

inline int generateLevel()
{
    int level = 1;

    for ( int R = rand() % ( 1 << (MAX_LEVEL - 1) ); ( R & 1 ) == 1; R >>= 1 )
        level++;

    assert( level < MAX_LEVEL );

    return level;
}

void search(int& current, const int value)
{
    for ( int i = 0; i < MAX_LEVEL; ++i )
    {
        jumped[i] = 0;
        levelNode[i] = 0;
    }

    for ( int l = maxLevel - 1; l >= 0; l-- )
    {
        while ( SL[ SL[current + l + 1] ] < value )
        {
            jumped[l] += width[current + l + 1];
            current = SL[current + l + 1];
        }

        levelNode[l] = current;
    }
}

void insert(const int value)
{
    int current = 0;
    search(current, value);

    current = SL[current + 1];

    if ( /**value != SL[current]**/ 1 == 1 )
    {
        int newLevel = generateLevel();

        if ( newLevel > maxLevel )
            maxLevel = newLevel;

        SL[pointer] = value;
        int J = 0;

        for ( int l = 0; l < newLevel; ++l )
        {
            SL[pointer + l + 1] = SL[levelNode[l] + l + 1];
            SL[levelNode[l] + l + 1] = pointer;

            width[pointer + l + 1] = width[levelNode[l] + l + 1] - J;
            width[levelNode[l] + l + 1] = J + 1;

            J += jumped[l];
        }

        for ( int l = newLevel; l < MAX_LEVEL; ++l )
            width[levelNode[l] + l + 1]++;

        pointer += newLevel + 1;

        assert( pointer < SIZE_SKIPLIST );
    }
}

bool find(const int value)
{
    int current = 0;
    search(current, value);

    current = SL[current + 1];

    return ( value == SL[current] );
}

void erase(const int value)
{
    int current = 0;
    search(current, value);

    current = SL[current + 1];

    if ( SL[current] == value )
    {
        for ( int l = 0; l < maxLevel; ++l )
        {
            if ( SL[levelNode[l] + l + 1] == current )
            {
                SL[levelNode[l] + l + 1] = SL[current + l + 1];
                width[levelNode[l] + l + 1] += width[current + l + 1] - 1;
            }
            else
            {
                width[levelNode[l] + l + 1]--;
            }
        }
    }
}

int kth_element(int k)
{
    int current = 0;

    for ( int l = maxLevel - 1; l >= 0; l-- )
    {
        while ( SL[ SL[current + l + 1] ] != INF && width[current + l + 1] < k )
        {
            k -= width[current + l + 1];
            current = SL[current + l + 1];
        }
    }

    current = SL[current + 1];

    return SL[current];
}

void printList()
{
    int current = 0;

    while ( SL[current] != INF )
    {
        cerr << SL[current] << " ";
        current = SL[current + 1];
    }
}

int main()
{
//    cerr << fixed << setprecision( 10 );
//    cerr << "Memory: " << getMemory() << "\n";

    initSkiplist();

    ifstream in("hashuri.in");
    ofstream out("hashuri.out");

    ios_base::sync_with_stdio( false );

    int N;
    in >> N;

    while ( N-- )
    {
        int tip, x;

        in >> tip >> x;

        switch(tip)
        {
            case 1: insert(x); break;
            case 2: erase(x); break;
            case 3: out << find(x) << "\n"; break;

            default: cerr << "Error\n";
        }
    }

    return 0;
}