Cod sursa(job #961263)

Utilizator primulDarie Sergiu primul Data 11 iunie 2013 20:19:08
Problema Eprubeta Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.52 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;  
}  
   
/* 
void recursive_print(skl* lista) { 
    if (lista == NULL) return; 
  
    static int level = -1; 
    ++level; 
  
    printf("%3d ", lista->sum); 
    recursive_print(lista->left); 
  
    printf("\n    "); 
    for (int i = 0; i < level; ++i) 
        printf("    "); 
    recursive_print(lista->right); 
  
    --level; 
} 
  
int recursive_check(skl* lista) { 
    if (lista->end - lista->begin == 1) 
        return lista->sum; 
  
    assert(lista->sum == recursive_check(lista->left) + 
                         recursive_check(lista->right)); 
    return lista->sum; 
} 
  
void print(skl* lista, const char* name) { 
    printf("=============================\n"); 
    printf("%s:\n", name); 
  
    recursive_print(lista); 
    printf("\n"); 
    recursive_check(lista); 
  
    printf("*****************************\n"); 
} 
  
#define print(lista) print(lista, #lista) 
*/ 
   
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) {  
        // partea dreapta trebuie intershimbata  
        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);  
    }  
   
    // facem update la suma  
    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;  
   
        // creem prima lista (stanga)  
        if (i != 0) {  
            int temp[maxN] = { 0 };  
            copy(line, line + i, temp);  
            reverse(temp, temp + i);  
   
            lst[i][0] = create(temp, 0, N, i);  
        }  
   
        // creem a doua lista (dreapta)  
        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);  
   
        // verificam conditiile  
        assert(0 <= a && a < N);  
        assert(0 <= b && b < N);  
        assert(o == 1 || o == 2);  
        assert(a <= b);  
   
        // executam operatiile  
        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 {  
            // interogare  
            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;  
}