ZOJ3765 Lights Splay树

非常裸的一棵Splay树,需要询问的是区间gcd,但是区间上每个数分成了两种状态,做的时候分别存在val[2]的数组里就好。区间gcd的时候基本上不支持区间的操作了吧。。不然你一个区间里加一个数gcd都不知道怎么维护了,所以维护点的gcd是比较简单的,题目存在删除和增加,所以Splay树无误了。删除一个结点或区间的方法是先把它get出来,然后令root->ch[1]->ch[0]=null,记得每次操作完要提根。

#pragma warning(disable:4996)

#include<cstring>

#include<string>

#include<cstdio>

#include<iostream>

#define ll long long

#define maxn 401000

using namespace std;



int n, q;



int gcd(int a, int b)

{

	while (a&&b) { a %= b; a ^= b; b ^= a; a ^= b; }

	return a + b;

}



struct Node

{

	Node *ch[2], *p;

	int size, val[2], gval[2];

	int status;

	Node(){

		size = 0; val[0] = val[1] = 0; status = 0; gval[0] = gval[1] = 0;

	}

	bool d() {

		return this == p->ch[1];

	}

	void setc(Node *c, int d){

		ch[d] = c; c->p = this;

	}

	void cvalIt(int cval){

		val[status] = cval;

		gval[status] = gcd(val[status],gcd(ch[0]->gval[status], ch[1]->gval[status]));

	}

	void cstaIt(){

		swap(val[status ^ 1], val[status]);

		gval[status] = gcd(ch[0]->gval[status], ch[1]->gval[status]);

		gval[status ^ 1] = gcd(gval[status ^ 1], gcd(ch[0]->gval[status ^ 1], ch[1]->gval[status ^ 1]));

		status ^= 1;

	}

	void upd(){

		size = ch[0]->size + ch[1]->size + 1;

		for (int i = 0; i < 2; i++){

			gval[i] = gcd(gcd(ch[0]->gval[i], ch[1]->gval[i]), val[i]);

		}

	}

}Tnull,*null=&Tnull;



Node mem[maxn], *C = mem;



Node*make(int v, int sta){

	C->ch[0] = C->ch[1] = null;

	C->size = 1;

	C->val[sta] = v; C->val[sta ^ 1] = 0;

	C->gval[sta] = v; C->gval[sta ^ 1] = 0;

	C->status = sta;

	return C++;

}



int ax[maxn], bx[maxn];



Node*build(int l, int r)

{

	if (l >= r) return null;

	int m = (l + r) >> 1;

	Node *t = make(ax[m], bx[m]);

	t->setc(build(l, m), 0);

	t->setc(build(m + 1, r), 1);

	t->upd();

	return t;

}



Node *root;

void rot(Node*t) {

	Node*p = t->p;

	//p->relax();

	//t->relax();

	int d = t->d();

	p->p->setc(t, p->d());

	p->setc(t->ch[!d], d);

	t->setc(p, !d);

	p->upd();

	if (p == root)

		root = t;

}



void splay(Node*t, Node*f = null) {

	while (t->p != f) {

		if (t->p->p == f)

			rot(t);

		else

			t->d() == t->p->d() ? (rot(t->p), rot(t)) : (rot(t), rot(t));

	}

	t->upd();

}



Node* select(int k) {

	for (Node*t = root;;) {

		//t->relax();

		int c = t->ch[0]->size;

		if (k == c)

			return t;

		if (k > c)

			k -= c + 1, t = t->ch[1];

		else

			t = t->ch[0];

	}

}



Node*&get(int l, int r) { //[l,r)

	Node*L = select(l - 1);

	Node*R = select(r);

	splay(L);

	splay(R, L);

	return R->ch[0];

}



void print(Node* x)

{

	if (x == null) return;

	print(x->ch[0]);

	printf(" %d", x->val[0]);

	print(x->ch[1]);

}











int main()

{

	while (~scanf("%d%d", &n, &q))

	{

		for (int i = 1; i <= n; i++){

			scanf("%d%d", &ax[i], &bx[i]);

		}

		C = mem;

		ax[0] = ax[n + 1] = 0; bx[0] = bx[n + 1] = 0;

		root = build(0, n + 2); root->p = null;

		char type[3];

		int li, ri, si,vi;

		for (int i = 0; i < q; i++){

			scanf("%s", type);

			if (type[0] == 'Q'){

				scanf("%d%d%d", &li, &ri, &si);

				Node* &t=get(li, ri+1);

				if (t->gval[si]) {

					printf("%d\n", t->gval[si]);

				}

				else puts("-1");

			}

			else if (type[0] == 'I'){

				scanf("%d%d%d", &li, &vi, &si);

				Node *&t = get(li, li + 1);

				t->ch[1] = make(vi, si);

				splay(t);

			}

			else if (type[0] == 'D' ){

				scanf("%d", &li);

				Node *&t = get(li, li+1);

				root->ch[1]->ch[0] = null;

				splay(root->ch[1]);

			}

			else if (type[0] == 'R'){

				scanf("%d", &li);

				Node *&t = get(li, li + 1);

				t->cstaIt();

				splay(t);

			}

			else if (type[0] == 'M'){

				scanf("%d%d", &li, &vi);

				Node *&t = get(li, li + 1);

				t->cvalIt(vi);

				splay(t);

			}

		}

	}

	return 0;

}

 

你可能感兴趣的:(play)