Cod sursa(job #141530)

Utilizator GiggityGlen Quagmire Giggity Data 23 februarie 2008 12:52:35
Problema Eprubeta Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.78 kb
#include<iostream>
#include<cmath>

using namespace std;

const int NMAX = 2048;

struct T
{
	T *next, *peste;
	int s;
	int val;
};

struct DP
{
	T *left, *right;
	DP *next, *prev;
	int val;
};

void read();
void update(int x, int y);
int query(int x, int y);
int qry(T *a, int c);
T* cauta(T* h, int x);
void recalc(T *a, T *b);
void afiseaza();
void go(T *a);

int N, M, D;
DP* start;

int main()
{
	freopen("eprubeta.in", "r", stdin);
	freopen("eprubeta.out", "w", stdout);

	read();

	return 0;
}

void read()
{
	int A, B, Z, sum;
	T *x; T *z; T *ls; DP *y; DP* last = 0;
	int i, j;

	cin >> N >> M >> Z >> A >> B;
	D = (int) sqrt((double)N);

	for(i = N - 1; i >= 0; i--)
	{
		y = new DP;
		y->next = last;
		y->val = ((i + A) * (i + B) / 4) % Z;
		last = y;
	}
	start = last;
	last = 0;

	for(i = 0, y = start; i < N; i++, y = y->next)
		y->prev = last, last = y;
	
	for(i = 0, y = start; i < N; i++, y = y->next)
	{
		ls = 0;
		for(j = N - 1; j > i; j--)
		{
			x = new T;
			x->next = ls;
			x->val = ((i + A) * (j + B) / 4) % Z;
			ls = x;
		}
		y->right = ls;
		ls = 0;
		for(j = 0; j < i; j++)
		{
			x = new T;
			x->next = ls;
			x->val = ((i + A) * (j + B) / 4) % Z;
			ls = x;
		}
		y->left = ls;
	}
	for(i = 0, y = start; i < N; i++, y = y->next)
	{
		sum = 0;

		for(j = i + 1, z = y->right; j < N && j <= i + D; z = z->next, j++)
			sum += z->val;

		for(j = i + 1, x = y->right; j < N; j++, x = x->next, z = (z != 0 ? z->next : 0))
		{
			x->peste = z;
			x->s = sum;
			sum -= x->val, sum += (z != 0 ? z->val : 0);
		}

		sum = 0;

		for(j = i - 1, z = y->left; j >= 0 && i - j <= D; z = z->next, j--)
			sum += z->val;

		for(j = i - 1, x = y->left; j >= 0; j--, x = x->next, z = (z != 0 ? z->next : 0))
		{
			x->peste = z;
			x->s = sum;
			sum -= x->val, sum += (z != 0 ? z->val : 0);
		}
	}

	int ch, xx, yy;
	long long mod, rez, ok;

	mod = 1;
	for(ch = 0; ch < 32; ch++)
		mod <<= 1;

	for(; M--;)
	{
	cin >> ch >> xx >> yy;
	if(ch == 1)
	{
		update(xx, yy);
		//afiseaza();
	}
	else cout << query(xx, yy) << "\n";
	}

	rez = 0;
	for(i = 0, y = start; i < N; i++, y = y->next)
	{
		ok = qry(y->right, N - i - 1) + y->val + qry(y->left, i);
		rez += (ok * ok % mod) * (i + 1) % mod, rez %= mod;
	}
	cout << rez << "\n";
}

void update(int x, int y)
{
	T *a, *aa, *wh;
	DP *b, *c;

	int i, z;

	for(i = 0, b = start; i < x; i++, b = b->next);
	for(c = b; i < y; c = c->next, i++);

	for(i = x; i <= y; i++, b = b->next, c = c->prev)
	{
		a = cauta(b->right, y - i - D + 1);
		aa = cauta(b->right, y - i);
		wh = cauta(c->left, y - i + 1);
		
		if(i != y)
		{
		recalc(a, aa);

		z = y - i;

		for(; z < D; z++, wh = wh != 0 ? wh->next : 0)
			a->s += wh != 0 ? wh->val : 0;

		for(; a != aa;)
		{
			a->peste = wh;
			if(a != aa)
				a->next->s = a->s - a->val + (wh != 0 ? wh->val : 0);
			wh = wh != 0 ? wh->next : 0;
			a = a->next;
		}
		aa->peste = wh;
		}

		a = cauta(b->left, i - x - D + 1);
		aa = cauta(b->left, i - x);
		wh = cauta(c->right, i - x + 1);

		if(i != x)
		{
		recalc(a, aa);

		z = i - x;

		for(; z < D; z++, wh = wh != 0 ? wh->next : 0)
			a->s += wh != 0 ? wh->val : 0;

		for(; a != aa;)
		{
			a->peste = wh;
			if(a != aa)
				a->next->s = a->s - a->val + (wh != 0 ? wh->val : 0);
			wh = wh != 0 ? wh->next : 0;
			a = a->next;
		}
		aa->peste = wh;
		}
	}
	for(i = 0, b = start; i < x; i++, b = b->next);
	for(c = b; i < y; c = c->next, i++);

	for(i = x; i < y; i++, b = b->next, c = c->prev)
	{
			if(i <= ((x + y) >> 1))
		{
			if(b != c)
			{
			if(i != y)
			{
			a = cauta(b->right, y - i);
			wh = cauta(c->left, y - i);
			aa = a->next;
			a->next = wh->next;
			wh->next = aa;
			}

			if(i != x)
			{
			a = cauta(b->left, i - x);
			wh = cauta(c->right, i - x);
			aa = a->next;
			a->next = wh->next;
			wh->next = aa;
			}
			}
			else
			{
				if(x != y)
				{
					a = cauta(b->right, y - i);
					wh = cauta(b->left, y - i);
					aa = a->next, a->next = wh->next, wh->next = aa;
				}
			}
		}
	}
	for(i = 0, b = start; i < x; i++, b = b->next);
	for(c = b; i < y; c = c->next, i++);

	for(i = x; i < y; i++, b = b->next, c = c->prev)
	{
		if(x != y)
			if(i !=x)
				a = b->left, b->left = b->right, b->right = a;
			else if(i == x)
					a = b->left, b->left = b->right, b->right = c->right, c->right = c->left, c->left = a;
			else;
		else;
	}
	for(i = 0, b = start; i < x; i++, b = b->next);
	for(c = b; i < y; i++, c = c->next);

	DP *u, *vv;

	vv = b->prev;

	for(u = b; u != c; u = u->next)
		u->prev = u->next;

	if(vv)
	vv->next = c;
	c->prev = vv;

	b->next = c->next;
	if(c->next)
	c->next->prev = b;

	for(; b != c; b = b->prev)
		b->prev->next = b;
}

T* cauta(T* h, int x)
{
	T *y;

	if(x <= 0) return h;

	for(y = h; x > D; x -= D)
	y = y->peste;

	for(; x > 1; x--)
		y = y->next;

	return y;
}

void recalc(T *a, T *b)
{

	if(a == b)
	{
		a->s = a->val;
		return;
	}
	recalc(a->next, b);
	a->s = a->val + a->next->s;
}

int query(int x, int y)
{
	DP *a;
	int sum = 0;
	int i;

	for(i = 0, a = start; i < x; i++, a = a->next);

	for(i = x; i <= y; i++, a = a->next)
		sum += qry(a->right, y - i) + qry(a->left, i - x) + a->val;

	return sum;
}

int qry(T *a, int c)
{
	int s = 0;

	for(; c >= D; c -= D)
		s += a->s, a = a->peste;

	for(; c; c--)
		s += a->val, a = a->next;

	return s;
}

void afiseaza()
{
	DP *y;
	int i;
	T *x;

	for(i = 0, y = start; i < N; i++, y = y->next)
	{
		go(y->left);
		cout << y->val << " ";
		for(x = y->right; x; x = x->next)
			cout << x->val << " ";
		cout << "\n";
	}
}

void go(T *a)
{
	if(!a)
		return;
	go(a->next);
	cout << a->val << " ";
}