Cod sursa(job #1764794)

Utilizator ReksioCroftOctavian Florin Staicu ReksioCroft Data 25 septembrie 2016 21:44:23
Problema Secventa 5 Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 3.76 kb
#include <stdio.h>
#define nmax ( 1 << 20 )
#define mod 702113
unsigned int v[nmax+1];          ///valorile initiale
unsigned int val[2][nmax];      ///valorile adaugate pe parcurs in lista
int next[2][nmax+1];           ///parcurerea listei
int frecv[2][nmax+1];         ///frecventa unui element in lista
int lasthash[2][mod];        ///ultimul nr cu acel cod hash
int poz, size, n, start, stop, ver;

int caut( unsigned int nr ){
    unsigned int h = nr % mod;
    int pozcaut = lasthash[ver][h];
    while( pozcaut!=0 && val[ver][pozcaut]!=nr )    ///cat timp nu am gasit elementul
        pozcaut = next[ver][pozcaut];
    return pozcaut;                 ///daca nu e gasit retunam 0, altfel returnam pozitia sa
}

void insert( unsigned int nr ){
    int pozinsert = caut( nr );                       ///caut daca a mai fost introdus
    unsigned int h = nr % mod;
    if( pozinsert!=0 && frecv[ver][pozinsert]!=0 )  ///daca a mai fost introdus, incrementam frecventa
        frecv[ver][pozinsert]++;
    else{                                            ///daca este porima oara
        val[ver][++poz] = nr;                       ///adaugam in lista simplu inlantuita
        next[ver][poz] = lasthash[ver][h];
        lasthash[ver][h] = poz;
        frecv[ver][poz] = 1;                      ///apare prima data
        size++;                                  ///inca un element distinct
    }

}

void sterge( unsigned int nr ){
    unsigned int h = nr % mod;
    int pozsters = lasthash[ver][h];             ///initializam cu capul listei
    if( val[ver][pozsters]==nr ){               ///daca e chiar capul
        frecv[ver][pozsters]--;                ///decrementam nr aparitii
        if( frecv[ver][pozsters]==0 ){              ///daca am ajuns la 0 scoatem elementul din lista
            lasthash[ver][h] = next[ver][pozsters];
            size--;                                ///si decrementa numarul de elemente distincte din secventa
        }
    }
    else{                                                                            ///daca nu e la capul listei
        while( val[ver][ next[ver][pozsters] ]!=nr && next[ver][pozsters]!=0 )      ///parcurgem lista
            pozsters = next[ver][pozsters];
        if( val[ver][ next[ver][pozsters] ]==nr ){             ///daca l-am gasit
            frecv[ver][ next[ver][pozsters] ]--;              ///decrementam nr aparitii
            if( frecv[ver][ next[ver][pozsters] ] == 0 ){    ///daca am ajuns la 0 scoatem elementul din lista
                size--;                                     ///si decrementa numarul de elemente distincte din secventa
                next[ver][pozsters] = next[ver][ next[ver][pozsters] ];
            }
        }
    }
}

long long lung( int max ){
    poz = size = 0;
    int pozst = 0;
    long long co = 0LL;
    int i;
    for( i=0; i<n; i++ ){   ///parcurgem elementele
        insert( v[i] );     ///le adaugam
        while( size > max ){    ///in momentul in care depasim limita stergem elementele de inceput ale secventei
            sterge( v[pozst] );
            pozst++;
        }
        co += i - pozst + 1;    ///contor ce retine nr de secvente; +1 => identat de la 0
    }
    return co;
}

int main()
{
    long long co;
    int i;
    FILE *fin, *fout;
    fin = fopen( "secv5.in", "r" );
    fscanf( fin, "%d%d%d", &n, &start, &stop );
    for( i=0; i<n; i++ )    ///citesc elementele
        fscanf( fin, "%u", &v[i] );
    fclose( fin );
    ver = 0;
    ///nr de secvente este diferenta dintre nr de secvente maimale si nr secvente minimae
    co = lung( stop );
    ver = 1;
    co -= lung( start - 1 );
    fout = fopen( "secv5.out", "w" );
    fprintf( fout, "%lld\n", co );
    fclose( fout );
    return 0;
}