Pagini recente » Cod sursa (job #940417) | Cod sursa (job #193769) | Cod sursa (job #444784) | Cod sursa (job #2318514) | Cod sursa (job #1463885)
#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;
}