非常裸的一棵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; }