Cod sursa(job #313014)

Utilizator ScrazyRobert Szasz Scrazy Data 7 mai 2009 18:47:03
Problema Eprubeta Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.98 kb
//Copied from M. Pasoi
//Educational purposes only :)
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>

using namespace std;

#define MAX_N 2048
#define INF 0x3f3f3f3f
#define MAX_PRIORITY 32767
#define MAX_NODES 4000025
#define FIN "eprubeta.in"
#define FOUT "eprubeta.out"
#define update(n) (sum[n] = sum[left[n]] + sum[right[n]] + val[n])
#define NIL 0 

short key[MAX_NODES], pri[MAX_NODES];
unsigned char val[MAX_NODES];
int sum[MAX_NODES], left[MAX_NODES], right[MAX_NODES];
int pool[MAX_NODES], pool_size;

int N, M, A, B, X, V[MAX_N], L[MAX_N], R[MAX_N];

inline void rotleft(int &n) 
{ 
    int t = left[n];
    left[n] = right[t];
    update(n);
    right[t] = n;
    n = t;
    update(n);
}

inline void rotright(int &n) 
{ 
    int t = right[n];
    right[n] = left[t];
    update(n);
    left[t] = n;
    n = t;
    update(n);
}

inline int new_node(short k, int v, short p, int l, int r) 
{
    int t = pool[--pool_size];
    key[t] = k; val[t] = v; pri[t] = p;
    left[t] = l; right[t] = r;
    return t; 
}

inline void delete_node(int n)
{
    key[n] = val[n] = pri[n] = 0;
    left[n] = right[n] = 0;
    pool[pool_size] = n;
}

void insert(int &n, short k, int v, short p)
{
    if (n == NIL)
    {
        n = new_node(k, v, p, NIL, NIL);
        update(n);
        return;
    }
    if (k < key[n])
    {
        insert(left[n], k, v, p);
        if (pri[left[n]] > pri[n]) rotleft(n);
    }
    else 
    {
        insert(right[n], k, v, p);
        if (pri[right[n]] > pri[n]) rotright(n);
    }
    update(n);
}

void erase(int &n)
{
    if (left[n] == NIL && right[n] == NIL) { delete_node(n); n = NIL; return; }
    if (pri[left[n]] > pri[right[n]])
    {
        rotleft(n);
        erase(right[n]);
    }
    else
    {
        rotright(n);
        erase(left[n]);
    }
    update(n);
}

int join(int n1, int n2)
{
    int n = new_node(0, 0, MAX_PRIORITY, n1, n2);
    erase(n);
    return n;
}

int split(int &n, short key)
{
    int n1, n2;

    insert(n, key, 0, MAX_PRIORITY);
    n1 = left[n]; n2 = right[n];
    delete_node(n);
    n = n2; 
    return n1;
}

void rotate(int &n1, int &n2, int size)
{
    int t1, t2;

    t1 = split(n1, size);
    t2 = split(n2, size);
    n2 = join(t1, n2);
    n1 = join(t2, n1);
}

int get_sum(int n, short k)
{
    if (n == NIL) return 0;
    if (k < key[n]) return get_sum(left[n], k);
    if (k == key[n]) return sum[left[n]]+val[n];
    return sum[left[n]]+val[n]+get_sum(right[n], k);
}

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

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

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

    for (i = 1; i < MAX_NODES; ++i)
        pool[pool_size++] = i;
    pri[NIL] = -MAX_PRIORITY;

    for (i = 0; i < N; ++i)
    {
        L[i] = R[i] = NIL;
        for (j = 0; j < N; ++j)
        {
            x = ((i+A)*(j+B)/4) % X;
            if (j < i) insert(L[i], i-j, x, rand()%MAX_PRIORITY);
            if (j > i) insert(R[i], j-i, x, rand()%MAX_PRIORITY);
            if (j == i) V[i] = x;
        }
    }

    for (; M; --M)
    {
        scanf("%d %d %d", &x, &i, &j);
        if (M == 9)
           k++;
        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 
        {
            for (s = 0, x = k = j-i; i <= j; ++i, --k)
            {
                s += get_sum(L[i], x-k); 
                s += get_sum(R[i], k);
                s += V[i];
            }
            printf("%d\n", s);
        }
    }

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

    return 0;
}