#include<bits/stdc++.h>
#define root_right ch[root][1]
using namespace std;
const int MX = 4e5 + 5;
int a[MX], S[MX], n;
int root, rear; //根节点,节点总数
int rem[MX], tot; //经过删除后未被使用的节点
int ch[MX][2], fa[MX];
int val[MX], sum[MX][2];
int sta[MX];
int sz[MX];
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
void NewNode(int &rt, int father, int v, int s) {
if (tot) rt = rem[tot--];
else rt = ++rear;
fa[rt] = father;
ch[rt][0] = ch[rt][1] = 0;
val[rt] = v;
sta[rt] = s;
sum[rt][s] = v;
sum[rt][s ^ 1] = 0;
sz[rt] = 1;
}
void PushUP(int rt) {
int ls = ch[rt][0], rs = ch[rt][1];
sz[rt] = sz[ls] + sz[rs] + 1;
sum[rt][0] = gcd(sum[ls][0], sum[rs][0]);
sum[rt][1] = gcd(sum[ls][1], sum[rs][1]);
if (sta[rt] == 0) sum[rt][0] = gcd(sum[rt][0], val[rt]);
else sum[rt][1] = gcd(sum[rt][1], val[rt]);
}
void build(int &rt, int l, int r, int father) {
if (l > r) return;
int m = (l + r) >> 1;
NewNode(rt, father, a[m], S[m]);
build(ch[rt][0], l, m - 1, rt);
build(ch[rt][1], m + 1, r, rt);
PushUP(rt);
}
void init() {
root = rear = tot = 0;
NewNode(root, 0, 0, 0); //一共n+2个节点
NewNode(ch[root][1], root, 0, 0);
for (int i = 1; i <= n; i++) scanf("%d%d", &a[i], &S[i]);
build(ch[ch[root][1]][0], 1, n, ch[root][1]);
PushUP(root);
}
void Rotate(int rt, int op) { //op=0表示左旋,op=1表示右旋
int father = fa[rt];
//PushDown(father); PushDown(rt);
ch[father][!op] = ch[rt][op];
fa[ch[rt][op]] = father;
if (fa[father])
ch[fa[father]][ch[fa[father]][1] == father] = rt;
fa[rt] = fa[father];
ch[rt][op] = father;
fa[father] = rt;
PushUP(father); //father变成子节点,只要更新father
}
void Splay(int rt, int f) {
//PushDown(rt);
while (fa[rt] != f) {
int father = fa[rt];
if (fa[father] == f) Rotate(rt, ch[father][0] == rt);
else {
int gf = fa[father];
if (ch[gf][0] == father) {
if (ch[father][0] == rt) Rotate(father, 1), Rotate(rt, 1);
else Rotate(rt, 0), Rotate(rt, 1);
} else {
if (ch[father][1] == rt) Rotate(father, 0), Rotate(rt, 0);
else Rotate(rt, 1), Rotate(rt, 0);
}
}
}
PushUP(rt); //更新rt
if (f == 0) root = rt;
}
int get_kth(int rt, int k) {
int t = sz[ch[rt][0]] + 1, ret;
if (t == k) ret = rt;
else if (t > k) ret = get_kth(ch[rt][0], k);
else ret = get_kth(ch[rt][1], k - t);
return ret;
}
int Query(int L, int R, int s) {
Splay(get_kth(root, L), 0); //将第L-1个数旋转到根节点
Splay(get_kth(root, R + 2), root); //将第R+1个数旋转到根节点的右儿子
int ans = sum[ch[ch[root][1]][0]][s];
return ans == 0 ? -1 : ans;
}
void Insert(int p, int v, int s) {
Splay(get_kth(root, p + 1), 0); //将第p个数旋转到根节点
Splay(get_kth(root, p + 2), root); //将第p+1个数旋转到根节点的右儿子,此时该节点没有左儿子
NewNode(ch[ch[root][1]][0], ch[root][1], v, s);
PushUP(ch[root][1]);
PushUP(root);
}
void erase(int rt) {
if (!rt)return;
fa[rt] = 0;
rem[++tot] = rt;
erase(ch[rt][0]);
erase(ch[rt][1]);
}
void Delete(int p) {
Splay(get_kth(root, p), 0); //将第p-1个数旋转到根节点
Splay(get_kth(root, p + 2), root);//将第p+1个数旋转到根节点的右儿子,此时该节点左儿子为p
erase(ch[ch[root][1]][0]);
ch[ch[root][1]][0] = 0;
PushUP(ch[root][1]);
PushUP(root);
}
void Change1(int p) {
Splay(get_kth(root, p + 1), 0); //将第p个数旋转到根节点
sta[root] ^= 1;
PushUP(root);
}
void Change2(int p, int v) {
Splay(get_kth(root, p + 1), 0); //将第p个数旋转到根节点
val[root] = v;
PushUP(root);
}
int main() {
//freopen("in.txt", "r", stdin);
int m, l, r, v, s, p; char op[2];
while (~scanf("%d%d", &n, &m)) {
init();
while (m--) {
scanf("%s", op);
if (op[0] == 'Q') {
scanf("%d%d%d", &l, &r, &s);
printf("%d\n", Query(l, r, s));
}
if (op[0] == 'I') {
scanf("%d%d%d", &p, &v, &s);
Insert(p, v, s);
}
if (op[0] == 'D') {
scanf("%d", &p);
Delete(p);
}
if (op[0] == 'R') {
scanf("%d", &p);
Change1(p);
}
if (op[0] == 'M') {
scanf("%d%d", &p, &v);
Change2(p, v);
}
}
}
return 0;
}
Splay树模板
最新推荐文章于 2024-05-07 12:24:19 发布