Cod sursa(job #253377)

Utilizator 630r63Ilinca George Mihai 630r63 Data 5 februarie 2009 18:41:26
Problema Eprubeta Scor 95
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.1 kb
 #include <cstdio>     
 #include <cassert>     
 #include <algorithm>     
     
 #define maxN 2048     
 #define INFI 0x3f3f3f3f     
     
 using namespace std;     
     
 struct skl {     
     int sum;     
     int right;     
     
     void update();     
 };     
     
 int N, M;     
 int dia[maxN];     
 int lst[maxN][2];     
     
 skl pool[2 * maxN * maxN];     
 int pool_head = 0;     
     
 inline void skl::update() {     
     sum = (this + 1)->sum;     
     if (right != INFI) sum += pool[right].sum;     
 }     
     

 int query_count = 0;     
     
 int create(int* line, int begin, int end, int limit) {     
     ++query_count;     
     
     if (begin >= limit) return INFI;     
     const int node = pool_head++;     
     
     if (end - begin != 1) {     
         const int mid = (begin + end) / 2;     
     
         create(line, begin, mid, limit);                   // left     
         pool[node].right = create(line, mid, end, limit);  // right     
         pool[node].update();     
     } else {     
         pool[node].right = INFI;     
         pool[node].sum = line[begin];     
     }     
     
     return node;     
 }     
     
 int query(int lista, int count) {     
     int sum = 0;     
     int begin = 0;     
     int end = N;     
     
     while (lista != INFI) {     
         ++query_count;     
     
         const int mid = (begin + end) / 2;     
         if (begin >= count) break;     
     
         if (mid <= count) {     
             if (end - begin > 1)     
                 sum += pool[lista+1].sum;     
     
             begin = mid;     
             lista = pool[lista].right;     
         } else {     
             end = mid;     
             ++lista;     
         }     
     }     
     
     return sum;     
 }     
     
 void mix(int first, int second, int begin, int end, int count) {     
     ++query_count;     
     
     // assert(first->begin == second->begin);     
     // assert(first->end == second->end);     
     
     if (end <= count) {     
         // intervalul e in partea stanga a liniei     
         return;     
     }     
     
     const int mid = (begin + end) / 2;     
     
     if (mid >= count) {     
    
         mix(first + 1, second + 1, begin, mid, count);     
         swap(pool[first].right, pool[second].right);     
     } else {     
         mix(pool[first].right, pool[second].right, mid, end, count);     
     }     
     
     
     pool[first].update();     
     pool[second].update();     
 }     
     
 void recursive_print_square(int lista, int begin, int end, bool dir) {     
     if (lista == INFI) return;     
     
     if (end - begin == 1) {     
         printf("%d ", pool[lista].sum);     
         return;     
     } else {     
         const int mid = (begin + end) / 2;     
     
         if (dir) {     
             recursive_print_square(pool[lista].right, mid, end, dir);     
             recursive_print_square(lista + 1, begin, mid, dir);     
         } else {     
             recursive_print_square(lista + 1, begin, mid, dir);     
             recursive_print_square(pool[lista].right, mid, end, dir);     
         }     
     }     
 }     
     
 void print_square() {     
     for (int i = 0; i < N; ++i) {     
         if (i != 0)     
             recursive_print_square(lst[i][0], 0, N, true);     
     
         printf("%d ", dia[i]);     
     
         if (i != N-1)     
             recursive_print_square(lst[i][1], 0, N, false);     
     
         printf("\n");     
     }     
 }     
     
 int main() {     
     freopen("eprubeta.in", "rt", stdin);     
     freopen("eprubeta.out", "wt", stdout);     
     
     scanf("%d %d", &N, &M);     
     
     int X, A, B;     
     scanf("%d %d %d", &X, &A, &B);     
     
     for (int i = 0; i < N; ++i) {     
         int line[maxN];     
         for (int j = 0; j < N; ++j)     
             line[j] = ((i + A) * (j + B) / 4) % X;     
     
         dia[i] = line[i];     
         lst[i][0] = lst[i][1] = INFI;     
     
    
         if (i != 0) {     
             int temp[maxN] = { 0 };     
             copy(line, line + i, temp);     
             reverse(temp, temp + i);     
     
             lst[i][0] = create(temp, 0, N, i);     
         }     
     
   
        if (i != N-1) {     
             int temp[maxN] = { 0 };     
             copy(line + i + 1, line + N, temp);     
     
             lst[i][1] = create(temp, 0, N, N - i - 1);     
         }     
     }     
     
     fprintf(stderr, "pool_head = %d\n", pool_head);     
     
     for (int i = 0; i < M; ++i) {     
         int o, a, b;     
         scanf("%d %d %d", &o, &a, &b);     
     
  
         assert(0 <= a && a < N);     
         assert(0 <= b && b < N);     
         assert(o == 1 || o == 2);     
         assert(a <= b);     
     
   
         if (o == 1) {     
             int l = b-a+1;     
             for (int j = 0; j < l-1; ++j) {     
                 mix(lst[a+j][1], lst[b-j][0], 0, N, l-j-1);     
                 swap(lst[a+j][1], lst[b-j][0]);     
             }     
     
             reverse(dia + a, dia + b + 1);     
         } else {     
       int sum = 0;     
     
             for (int j = a; j <= b; ++j) {     
                 sum += dia[j];     
     
                 if (j > a) sum += query(lst[j][0], j - a);     
                 if (j < b) sum += query(lst[j][1], b - j);     
             }     
     
             printf("%d\n", sum);     
         }     
     }     
     
     fprintf(stderr, "qc = %d\n", query_count);     
     
     unsigned int result = 0;     
     for (int i = 0; i < N; ++i) {     
         unsigned int sum = 0;     
     
         sum += dia[i];     
         if (i != 0) sum += pool[lst[i][0]].sum;     
         if (i != N-1) sum += pool[lst[i][1]].sum;     
     
         result += sum * sum * (i + 1);     
     }     
     printf("%u\n", result);     
     
     return 0;     
}