Pagini recente » Cod sursa (job #1443219) | Cod sursa (job #2973044) | Cod sursa (job #3257178) | Cod sursa (job #1132457) | Cod sursa (job #1463897)
#include <stdio.h>
#include <string.h>
#define MAX_N (1 << 20)
#define HASHSIZE 666013
#define h(X) ((X) - (X) / HASHSIZE * HASHSIZE)
#define NIL -1
typedef struct {
unsigned key;
int cnt;
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
unsigned v[MAX_N]; // sirul dat
int n; // lungimea sirului dat
static inline int hashRemove(const unsigned &q) {
int hq = h(q);
if (l[hash[hq]].key == q) { // daca se afla la capatul listei
l[hash[hq]].cnt--;
if (!l[hash[hq]].cnt) {
st[s++] = hash[hq];
hash[hq] = l[hash[hq]].next;
return NIL;
}
} 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) {
l[l[i].next].cnt--;
if (!l[l[i].next].cnt) {
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
return NIL;
}
}
}
return 0;
}
static inline int hashCount(const unsigned &q) {
int i = hash[h(q)];
while (i != NIL && l[i].key != q) {
i = l[i].next;
}
if (i != NIL) {
return l[i].cnt;
}
return 0;
}
static inline void hashInsert(const unsigned &q) {
int i = hash[h(q)];
while (i != NIL && l[i].key != q) {
i = l[i].next;
}
if (i != NIL) {
l[i].cnt++;
} else {
i = s ? st[--s] : buffPtr++;
l[i].key = q;
l[i].cnt = 1;
l[i].next = hash[h(q)];
hash[h(q)] = i;
}
}
static unsigned long long cntSecv(int x) {
int start;
int nDist;
unsigned long long 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 = 0ULL; // 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
nDist += hashRemove(v[start++]); // scad din numarul de numere distincte daca aceasta nu mai exista in hash
}
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, "%u", &v[i]);
}
fclose(f);
f = fopen("secv5.out", "w");
fprintf(f, "%llu\n", cntSecv(hi) - cntSecv(lo - 1)); // din numarul secventelor cu nr. distincte <= hi scad numarul secventelor cu nr. distincte < lo
fclose(f);
return 0;
}