Cod sursa(job #163028)

Utilizator FlorinC1996Florin C FlorinC1996 Data 21 martie 2008 09:24:50
Problema Eprubeta Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.65 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;   
}