Cod sursa(job #1463885)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 21 iulie 2015 19:08:33
Problema Secventa 5 Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.97 kb
#include <stdio.h>
#include <string.h>

#define MAX_N (1 << 20)
#define HASHSIZE 64
#define h(X) (((X * 123) & 1023) >> 4)
#define NIL -1

typedef struct {
  int key;
  int next;
} cell;

cell l[MAX_N];      // buffer prealocat
int buffPtr;        // ultima pozitie libera din buffer

int st[MAX_N];      // stiva de pozitii libere
int s;              // numarul de elemente din liste

int hash[HASHSIZE]; // capetele listelor, initializate cu NIL

int v[MAX_N];       // sirul dat
int n;              // lungimea sirului dat

static inline void hashRemove(const int &q) {
  int hq = h(q);

  if (l[hash[hq]].key == q) {   // daca se afla la capatul listei
    hash[hq] = l[hash[hq]].next;
  } else {
    int i = hash[hq];

    while (l[i].next != NIL && l[l[i].next].key != q) {
      i = l[i].next;
    }
    if (l[i].next != NIL) {
      st[s++] = l[i].next;            // retin in stiva de pozitii o noua pozitie libera
      l[i].next = l[l[i].next].next;  // sterg nodul din lista
    }
  }
}

static inline int hashCount(const int &q) {
  int count = 0;

  for (int i = hash[h(q)]; i != NIL; i = l[i].next) {
    count += (l[i].key == q);
  }
  return count;
}

static inline void hashInsert(const int &q) {
  int pos = s ? st[--s] : buffPtr++;  // va folosi o pozitie eliberata de o stergere, daca exista

  l[pos].key = q;
  l[pos].next = hash[h(q)];
  hash[h(q)] = pos;
}

static unsigned cntSecv(int x) {
  int start;
  int nDist;
  unsigned nSecv;

  // initializare hash
  memset(hash, NIL, sizeof(hash));  // capetele listelor pe NIL
  buffPtr = 0;                      // numarul de pozitii folosite in buffer
  s = 0;                            // numarul de pozitii eliberate prin stergere

  // initializare variabile
  start = 0; // secventa curenta este [start, i]
  nDist = 0; // numarul de elemente distincte in secventa curenta
  nSecv = 0; // numarul de secvente in care numarul de nr. distincte <= x

  for (int i = 0; i < n; i++) {
    if (!hashCount(v[i])) {       // daca apare pentru prima data
      nDist++;                    // cresc numarul de numere distincte
    }
    hashInsert(v[i]);
    while (nDist > x) {                // daca numarul de numere distincte este prea mare
      hashRemove(v[start]);            // micsorez secventa, cresc pozitia de start si elimin valorile din hash
      nDist -= (!hashCount(v[start])); // scad din numarul de numere distincte daca aceasta nu mai exista in hash
      start++;                         // cresc pozitia de start
    }
    nSecv += (i - start + 1);          // toate secventele din interiorul [start, i] au numar de numere distincte <= x
  }
  return nSecv;
}

int main(void) {
  FILE *f = fopen("secv5.in", "r");
  int lo, hi;

  fscanf(f, "%d%d%d", &n, &lo, &hi);

  for (int i = 0; i < n; i++) {
    fscanf(f, "%d", &v[i]);
  }
  fclose(f);

  f = fopen("secv5.out", "w");
  fprintf(f, "%u\n", cntSecv(hi) - cntSecv(lo - 1)); // din numarul secventelor cu nr. distincte <= hi scad numarul secventelor cu nr. distincte < lo
  fclose(f);
  return 0;
}