Cod sursa(job #9260)

Utilizator dominoMircea Pasoi domino Data 27 ianuarie 2007 12:52:59
Problema Secventa 5 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.83 kb
#include <stdio.h>
#include <stdlib.h>

#define MAX_N 1<<20
#define MAX_H 1<<18
#define HASH_SHIFT 14
#define FIN "secv5.in"
#define FOUT "secv5.out"

struct hash_line 
{
    unsigned val[4];
    int idx[4];
} H[2][MAX_H];

int N, L, R, A[MAX_N], cnt1[MAX_N], cnt2[MAX_N];
unsigned hash[2]; char buf[16];
long long Res;

inline int hash_insert(unsigned val, int idx)
{
    int i1, i2;
    hash_line *p1, *p2;

    p1 = H[0] + ((val * hash[0]) >> HASH_SHIFT);
    for (i1 = 0; i1 < 4 && p1->val[i1]; i1++)
        if (p1->val[i1] == val) return p1->idx[i1];
    
    p2 = H[1] + ((val * hash[1]) >> HASH_SHIFT);
    for (i2 = 0; i2 < 4 && p2->val[i2]; i2++)
        if (p2->val[i2] == val) return p2->idx[i2];

    if (i1 == 4 && i2 == 4)
    {
        fprintf(stderr, "REHASH!\n");
        return -1;
    }

    if (i1 > i2) 
        p2->val[i2] = val, p2->idx[i2] = idx;
    else 
        p1->val[i1] = val, p1->idx[i1] = idx;
    return idx;
}

inline int read_int(void)
{
    int n = 0;
    char *p;

    fgets(buf, sizeof(buf), stdin);
    for (p = buf; *p >= '0' && *p <= '9'; p++)
        n = n*10 + *p-'0';
    return n;
}

int main(void)
{
    int i, l1, l2, n1, n2;

    freopen(FIN, "r", stdin);
    freopen(FOUT, "w", stdout);

    scanf("%d %d %d\n", &N, &L, &R);
    srand(N);
    hash[0] = (rand()<<1)|1;
    hash[1] = (rand()<<1)|1;
    for (i = 0; i < N; i++)
        A[i] = hash_insert(read_int(), i);

    for (i = l1 = l2 = n1 = n2 = 0; i < N; i++)
    {
        if (++cnt1[A[i]] == 1) n1++;
        for (; n1 > R && l1 <= i; l1++)
            if (--cnt1[A[l1]] == 0) n1--;

        if (++cnt2[A[i]] == 1) n2++;
        for (; n2 >= L && l2 <= i; l2++)
            if (--cnt2[A[l2]] == 0) n2--;

        Res += l2-l1;
    }

    printf("%lld\n", Res);

    return 0;
}