Cod sursa(job #133933)

Utilizator dominoMircea Pasoi domino Data 10 februarie 2008 00:02:56
Problema Eprubeta Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.12 kb
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>

using namespace std;

#define MAX_N 2048
#define FIN "eprubeta.in"
#define FOUT "eprubeta.out"
#define SQRT 45

struct list
{
    int val[2];
    list *next[2];
} *L[MAX_N], *R[MAX_N], *NIL;

int N, M, A, B, Z, V[MAX_N], C[MAX_N];

list* find(list *L, int idx)
{
    list *p;
    
    for (p = L; idx >= SQRT; idx -= SQRT, p = p->next[1]);
    for (; idx > 0; --idx, p = p->next[0]);
    return p;
}

void update(list *&L, list *end)
{
    list *p;
    int cnt = SQRT;

    L->val[1] = 0;
    for (p = L; p != NIL && cnt; --cnt, p = p->next[0])
        L->val[1] += p->val[0];
    L->next[1] = p;
    for (p = L; p != end; p = p->next[0])
    {
        p->next[0]->next[1] = p->next[1]->next[0];
        p->next[0]->val[1] = p->val[1]-p->val[0]+p->next[1]->val[0];
    }
}

void make_list(int a, int b, list *&L)
{
    int i;
    list *p;

    if (a >= b) return;
    for (i = b-1; i >= a; --i)
    {
        p = new list;
        p->val[0] = C[i];
        p->val[1] = 0;
        p->next[0] = L;
        p->next[1] = NIL;
        L = p;
    }
    update(L, NIL);
}


void rotate(list *&L1, list *&L2, int size)
{
    list *p1, *q1, *p2, *q2;

    if (size <= 0) return;
    p1 = find(L1, size-1);
    q1 = find(L1, size-SQRT);
    p2 = find(L2, size-1);
    q2 = find(L2, size-SQRT);
    swap(p1->next[0], p2->next[0]);
    swap(L1, L2);
    update(q1, p1);
    update(q2, p2);
}

int get_sum(list *L, int idx)
{
    list *p;
    int sum = 0;

    for (p = L; idx >= SQRT; idx -= SQRT, p = p->next[1])
        sum += p->val[1];
    for (; idx > 0; --idx, p = p->next[0])
        sum += p->val[0];
    return sum;
}

int main(void)
{
    int i, j, k, x;

    freopen(FIN, "r", stdin);
    freopen(FOUT, "w", stdout);

    scanf("%d %d %d %d %d", &N, &M, &Z, &A, &B);

    NIL = new list;
    NIL->val[0] = NIL->val[1] = 0;
    NIL->next[0] = NIL->next[1] = NIL;
    
    for (i = 0; i < N; ++i)
    {
        for (j = 0; j < N; ++j)
        {
            C[j] = ((i+A)*(j+B)/4) % Z;
            if (j == i) V[i] = C[j];
        }
        reverse(C, C+i);
        L[i] = R[i] = NIL;
        make_list(0, i, L[i]);
        make_list(i+1, N, R[i]);
    }

    for (; M; --M)
    {
        scanf("%d %d %d", &x, &i, &j);
        if (x == 1)
        {
            for (x = k = j-i; i <= j; ++i, --j, --k)
            {
                rotate(L[j], R[i], k);
                if (i != j) rotate(L[i], R[j], x-k);
                swap(V[i], V[j]);
            }
        }
        else 
        {
            int sum = 0;
            for (x = k = j-i; i <= j; ++i, --k)
            {
                sum += get_sum(L[i], x-k); 
                sum += get_sum(R[i], k);
                sum += V[i];
            }
            printf("%d\n", sum);
        }
    }

    unsigned total_sum = 0;
    for (i = 0; i < N; ++i)
    {
        x = V[i]+get_sum(L[i], i)+get_sum(R[i], N-1-i);
        total_sum += (unsigned)x*(unsigned)x*(unsigned)(i+1);
    }
    printf("%u\n", total_sum);

    return 0;
}