Cod sursa(job #10533)

Utilizator alex_damianDamian Alexandru alex_damian Data 28 ianuarie 2007 16:43:46
Problema Secventa 5 Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.03 kb
#include <cstdio>

#define FIN "secv5.in"
#define FOUT "secv5.out"
#define MAXN 1100000

unsigned long a[MAXN][2], x;
long long sum;
long n, l, u, i, poz;
long NR;

struct point {
	long nr;
  point *zero, *unu;
} *prim;


void bag(unsigned long x) {
	point *q, *u;
  int bagat = 0;
  long i;
  u = prim;
  for (i=31; i>=0; i--) {
     q = new point;
     q->unu = NULL;
     q->zero = NULL;
    if (x & (unsigned long) (1<<i)) {
      if (u->unu == NULL) {
        bagat = 1;
        u->unu = q;
        u = u->unu;
      } else u = u->unu;
   	} else {
    	if (u->zero == NULL) {
        bagat = 1;
        u->zero = q;
        u = u->zero;
      } else u = u->zero;
    }
  }
  if (bagat || (u->nr == 0)) NR++;
  if (bagat) u->nr = 1; else u->nr++;
}


void scot(unsigned long x) {
	point *q;
  q = new point;
  q = prim;
  for (i=31; i>=0; i--) {
     if (x & (unsigned long) (1<<i)) q = q->unu; else q = q->zero;
  }
  q->nr--;
  if (q->nr == 0) NR--;
}

void solvegreu() {
  long poz, fin, i;
  unsigned long s;
  poz = 1;
  NR = 0;
  for (i=1; i<l; i++) bag(a[i][0]);
  s = 0;
  fin = l-1;
  while (NR<=u && fin<n) {
     bag(a[++fin][0]);
     s += a[fin][1];
  }
  if (NR>u) {
		scot(a[fin][0]);
  	s -= a[fin--][1];
  }
	sum += a[poz][1] * s;
  poz++;
  while (poz <= n-l+1) {
    scot(a[poz-1][0]);
    s -= a[poz+l-2][1];
    while (NR<=u && fin<n) {
      bag(a[++fin][0]);
      s += a[fin][1];
    }
  	if (NR>u) {
    	scot(a[fin][0]);
    	s -= a[fin--][1];
    }
    sum += a[poz][1] * s;
    poz++;
  }
}


int main () {
  freopen(FIN, "r", stdin);
  freopen(FOUT, "w", stdout);
	scanf("%ld %ld %ld", &n, &l, &u);

  poz = 1;
  scanf("%llu", &a[1][0]);
  a[1][1] = 1;

  for (i=2; i<=n; i++) {
     scanf("%llu", &x);
     if (x==a[poz][0]) a[poz][1]++;
     else {
       a[++poz][0] = x;
       a[poz][1] = 1;
     }
 	}
	n = poz;
  prim = new point;
  prim->zero = NULL;
  prim->unu = NULL;
  solvegreu();
  printf("%lld\n", sum);
  return 0;
}