Cod sursa(job #1693158)

Utilizator hrazvanHarsan Razvan hrazvan Data 22 aprilie 2016 15:49:59
Problema Eprubeta Scor 0
Compilator c Status done
Runda Arhiva de probleme Marime 4.83 kb
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define MAXNODES 4000000
#define MAXPR 32767
#define MAXN 2000
#define NIL 0
#define INF 2000000000
typedef struct nodul{
  int tata, left, right, poz, suma, pr, val;
}nod;
nod tr[MAXNODES + 1000];
int rd[MAXN], ld[MAXN];
int diag[MAXN];
int nnod = 1;

inline void init(int p, int tata, int left, int right, int poz, int pr, int val){
  tr[p].tata = tata;
  tr[p].left = left;
  tr[p].right = right;
  tr[p].poz = poz;
  tr[p].pr = pr;
  tr[p].val = val;
  tr[p].suma = val;
}

inline void rotate_left(int p){
  int aux, a;
  aux = tr[p].tata;
  a = tr[aux].suma;
  tr[aux].suma = tr[aux].suma - tr[p].suma + tr[tr[p].left].suma;
  tr[p].suma = a;
  tr[aux].right = tr[p].left;
  tr[tr[p].left].tata = aux;
  tr[p].left = aux;
  a = tr[aux].tata;
  tr[aux].tata = p;
  tr[p].tata = a;
  if(a != NIL){
    if(tr[a].left == tr[p].left)
      tr[a].left = p;
    else
      tr[a].right = p;
  }
}

inline void rotate_right(int p){
  int aux, a;
  aux = tr[p].tata;
  a = tr[aux].suma;
  tr[aux].suma = tr[aux].suma - tr[p].suma + tr[tr[p].right].suma;
  tr[p].suma = a;
  tr[aux].left = tr[p].right;
  tr[tr[p].right].tata = aux;
  tr[p].right = aux;
  a = tr[aux].tata;
  tr[aux].tata = p;
  tr[p].tata = a;
  if(a != NIL){
    if(tr[a].left == tr[p].right)
      tr[a].left = p;
    else
      tr[a].right = p;
  }
}

void add(int p, int poz, int pr, int val){
  if(p == NIL){
    init(nnod, NIL, NIL, NIL, poz, pr, val);
    nnod++;
  }
  else{
    tr[p].suma += val;
    if(poz < tr[p].poz){
      add(tr[p].left, poz, pr, val);
      if(tr[p].left == NIL)
        tr[p].left = nnod - 1;
      tr[tr[p].left].tata = p;
      if(tr[tr[p].left].pr > tr[p].pr)
        rotate_right(tr[p].left);
    }
    else{
      add(tr[p].right, poz, pr, val);
      if(tr[p].right == NIL)
        tr[p].right = nnod - 1;
      tr[tr[p].right].tata = p;
      if(tr[tr[p].right].pr > tr[p].pr)
        rotate_left(tr[p].right);
    }
  }
}

int suma(int p, int maxp){
  if(p == NIL)
    return 0;
  if(tr[p].poz > maxp)
    return suma(tr[p].left, maxp);
  if(tr[p].poz == maxp)
    return tr[p].val + tr[tr[p].left].suma;
  return tr[p].suma - tr[tr[p].right].suma + suma(tr[p].right, maxp);
}

inline void cobor(int p){
  while(tr[p].left != NIL || tr[p].right != NIL){
    if(tr[tr[p].left].pr > tr[tr[p].right].pr)
      rotate_right(tr[p].left);
    else
      rotate_left(tr[p].right);
  }
}

inline void join(int *r1, int r2){
  if(tr[*r1].poz < tr[r2].poz)
    init(nnod, NIL, *r1, r2, 0, -1, tr[*r1].suma + tr[r2].suma);
  else
    init(nnod, NIL, r2, *r1, 0, -1, tr[*r1].suma + tr[r2].suma);
  tr[*r1].tata = nnod;
  tr[r2].tata = nnod;
  cobor(nnod);
  int nr;
  if(tr[*r1].pr > tr[r2].pr)
    nr = *r1;
  else
    nr = r2;
  if(tr[tr[nnod].tata].left == nnod)
    tr[tr[nnod].tata].left = NIL;
  else
    tr[tr[nnod].tata].right = NIL;
  *r1 = nr;
}

inline int split(int *r, int maxp){
  add(*r, maxp, MAXPR + 1, 0);
  nnod--;
  tr[tr[nnod].left].tata = tr[tr[nnod].right].tata = NIL;
  (*r) = tr[nnod].right;
  return tr[nnod].left;
}

inline void rotate(int a, int b, int d){
  int p1, p2;
  p1 = split(&rd[a], d);
  p2 = split(&ld[b], d);
  join(&rd[a], p2);
  join(&ld[b], p1);
}

int main(){
  srand(time(0));
  tr[0].pr = -INF;
  FILE *in = fopen("eprubeta.in", "r");
  int n, m, z, a, b, i, j, x, q1, q2, q3;
  fscanf(in, "%d%d%d%d%d", &n, &m, &z, &a, &b);
  memset(rd, NIL, sizeof rd);
  memset(ld, NIL, sizeof ld);
  for(i = 0; i < n; i++){
    for(j = 0; j < i; j++){
      x = ((i + a) * (j + b) / 4) % z;
      add(ld[i], i - j, rand() % MAXPR, x);
      if(ld[i] == NIL)
        ld[i] = nnod - 1;
      while(tr[ld[i]].tata != NIL)
        ld[i] = tr[ld[i]].tata;
    }
    diag[i] = ((i + a) * (j + b) / 4) % z;
    for(j++; j < n; j++){
      x = ((i + a) * (j + b) / 4) % z;
      add(rd[i], j - i, rand() % MAXPR, x);
      if(rd[i] == NIL)
        rd[i] = nnod - 1;
      while(tr[rd[i]].tata != NIL)
        rd[i] = tr[rd[i]].tata;
    }
  }
  FILE *out = fopen("eprubeta.out", "w");
  int sum;
  for(i = 0; i < m; i++){
    fscanf(in, "%d%d%d", &q1, &q2, &q3);
    if(q1 == 1){
      a = q2;  b = q3;
      while(a < b){
        rotate(a, b, q3 - a);
        rotate(b, a, a - q2);
        a++;  b--;
      }
      a = diag[q2];  diag[q2] = diag[q3];  diag[q3] = a;
    }
    else{
      sum = 0;
      for(a = q2; a <= q3; a++)
        sum += suma(ld[a], a - q2) + suma(rd[a], q3 - a) + diag[a];
      fprintf(out, "%d\n", sum);
    }
  }
  unsigned int sumt = 0;
  for(i = 0; i < n; i++){
    sum = suma(ld[i], i) + suma(rd[i], n - i - 1) + diag[i];
    sumt += sum * sum * (i + 1);
  }
  fprintf(out, "%u", sumt);
  fclose(out);
  return 0;
}