Cod sursa(job #1302983)

Utilizator Impaler_009Mihai Nitu Impaler_009 Data 27 decembrie 2014 15:12:47
Problema Secventa 5 Scor 100
Compilator cpp Status done
Runda Teme Pregatire ACM Unibuc 2014, Anul I Marime 1.95 kb
#include <fstream>
using namespace std;

ifstream fin("secv5.in");
ofstream fout("secv5.out");
#define MOD 666013

int v[(1<<20)+1],freq[(1<<20)+1],freq2[(1<<20)+1];

int N,L,U,st,st2,l,nr,nr2,current;   //st- punctul de start ale celei mai lungi subsecvente ce se termina in punctul fixat l care are intre L si U elemente distincte
                                     //st2- punctul de start (+1) ale celei mai scurte subsecvente ce se termina in punctul fixat l care are intre L si U elemente distincte
                    // deoarece pe st2 il avansam cu o casuta ^  atunci st2-st este numarul total de subsecvente care se termina in punctul fixat l si au intre L si U elemente distincte, suma acestora pentru fiecare l ne da solutia

long long total;

struct node
{
    unsigned int x;
    int norm;
    node *next;
}*h[MOD];  //elementele sunt in intervalul [1,2^32] dar numarul lor este in intervalul [1,2^20]. Le normalizam valorile cu o tabela hash

int hash_search (unsigned int x)
{
    int j=x%MOD;
    for (node *d=h[j]; d!=NULL; d=d->next)
    {
        if (d->x==x) return d->norm;
    }
    return 0;
}

void hash_add (unsigned int x, int norm)
{
    int j=x%MOD;
    node *d= new node;
    d->x=x;
    d->norm=norm;
    d->next=h[j];
    h[j]=d;
}

void remove_elem (int &st, int &nr, int freq[])
{
    freq[v[st]]--;
    if (freq[v[st]]==0) nr--;
    st++;
}

void add (unsigned int x)
{
    int val= hash_search (x);

    if (val) v[l]=val;
    else {++current; v[l]=current; hash_add (x,current);}

    freq[v[l]]++; freq2[v[l]]++;
    if (freq[v[l]]==1) nr++;
    if (freq2[v[l]]==1) nr2++;
    while (nr2 >= L && st2<=l) remove_elem (st2,nr2,freq2);
}

int main()
{
    unsigned int x;
    fin>>N>>L>>U;
    for (st=1, st2=1 ,l=1; l<=N; l++)
    {
        fin>>x;
        add (x);
        while ( nr > U && st<=l) remove_elem (st,nr,freq);
        if (nr >= L)  total += st2-st;
    }
    fout<<total;
}