/* ********************************************** Author : wuyiqi Created Time: 2013-8-16 8:24:44 File Name : hdu 4680.cpp *********************************************** */ #pragma comment(linker,"/STACK:100000000,100000000") #include <cstring> #include <cstdio> #include <string> #include <iostream> using namespace std; #define L x->c[0] #define R x->c[1] #define KT root->c[1]->c[0] const int maxn = 300010; const int lim = 1000000000; inline int GCD(int a,int b) { if(a<0||a>lim) return b; if(b<0||b>lim) return a; return !b ? a : GCD(b,a%b); } struct node { struct node *c[2] , *fa; int id; int sz; int gcd; int val; int who; inline bool d() { return fa->c[0] == this; } inline void setc(int d,node *s) { c[d] = s; s->fa = this; } inline void up() { sz = c[0]->sz + c[1]->sz + 1; gcd = GCD(c[0]->gcd,c[1]->gcd); gcd = GCD(gcd,val); } inline void clear(node *null) { c[0] = c[1] = null; } }NODE[maxn] , *null = &NODE[0]; node* Q[maxn]; node* ID[maxn]; int Type; int n; int top; struct _x_x_{ int type; node* root; inline void Rotate(node *x,int f){ node *y = x->fa; y->setc(!f,x->c[f]); x->fa = y->fa; if(y->fa != null) y->fa->setc(!y->d(),x); x->setc(f,y); y->up(); } inline void Splay(node *x,node *goal) { while(x->fa!=goal) { if(x->fa->fa == goal) Rotate(x,x->d()); else { int f = x->fa->d(); x->d() == f ? Rotate(x->fa,f) : Rotate(x,!f); Rotate(x,f); } } x->up(); if(goal == null) { root = x; } } inline void RTO(int k,node *goal) { node *x = root; while(L->sz + 1 != k) { if(k < L->sz + 1) x = L; else { k -= L->sz + 1; x = R; } } Splay(x,goal); } inline node* new_node(node *fa,int v) { node *x = &NODE[++top]; x->id = top; x->c[0] = x->c[1] = null; x->sz = 1; x->val = v; x->gcd = v; x->fa = fa; ID[top] = x; return x; } inline void init(int v) { root = new_node(null,v); type = ++Type; root->who = type; } inline void Del_root() { node *t = root; if(t->c[1] != null) { root = t->c[1]; RTO(1,null); root->c[0] = t->c[0]; if(root->c[0] != null) root->c[0]->fa = root; } else { root = root->c[0]; } root->fa = null; if(root != null) root->up(); } inline void Delete(node *x) { Splay(x,null); Del_root(); } inline void Insert(node *x) { x->clear(null); //插入一个节点前不能忘记清空它的左右儿子 insert(root,x); Splay(x,null); x->who = type; } inline void insert(node* &x,node *y) { if(x == null) { x = y; return ; } if(y->val <= x->val) { insert(x->c[0],y); x->c[0]->fa = x; } else { insert(x->c[1],y); x->c[1]->fa = x; } x->up(); } inline void Insert(int v) { node *x = new_node(null,v); insert(root,x); Splay(x,null); x->who = type; } inline void Change(int u,int v) { node *tmp = ID[u+2*n]; Splay(tmp,null); Del_root(); tmp->val = v; Insert(tmp); } node *find_succ(node *x,int v) { if(x == null) return x; if(x->val == v) return x; else if(x->val > v) { node *tmp = find_succ(x->c[0],v); return tmp == null ? x : tmp; }else { return find_succ(x->c[1],v); } } inline int find_succ(int v){ node* tmp = find_succ(root,v); Splay(tmp,null) ; return tmp->val; } inline int Gao() { if(root->sz <= 4) return root->sz - 2; RTO(2,null); int a = root->val; RTO(3,null); int b = root->val; int ans = 2; while(true){ if(a + b > lim) break; int c = find_succ(a+b); if(c > lim || c == -1) break; a = b; b = c; ans++; } return ans; } void vist(node *x) { if(x != null) { printf("节点 %2d: 左儿子: %2d 右儿子: %2d sz:%2d val=%2d gcd: %2d\n",x->id,x->c[0]->id,x->c[1]->id,x->sz,x->val,x->gcd); vist(x->c[0]); vist(x->c[1]); } } void debug() { puts("******************************************"); vist(root); puts("*****************************************"); } node *Find_pre(node *x,int v) { if(x == null) return x; if(x->val < v) { node *tmp = Find_pre(x->c[1],v); return tmp == null ? x : tmp; } else { return Find_pre(x->c[0],v); } } node *Find_pre(int v) { node* tmp = Find_pre(root,v); Splay(tmp,null); return tmp; } node *Find_succ(node *x,int v) { if(x == null) return x; if(x->val > v) { node *tmp = Find_succ(x->c[0],v); return tmp == null ? x : tmp; } else { return Find_succ(x->c[1],v); } } node *Find_succ(int v) { node* tmp = Find_succ(root,v); Splay(tmp,null); return tmp; } void Assert(string s) { cout<<s<<endl; } int Solve(int l,int r) { node *pre = Find_pre(l); node *succ = Find_succ(r); if(pre == null || succ == null) Assert("越界了"); // printf("preid=%d succid=%d\n",pre->id,succ->id); // pre : the first element strictly less than l // succ: the first element strictly bigger than r Splay(pre,null); Splay(succ,root); return KT->gcd; } void Merge(_x_x_ &tree) { int head = 0, tail = 0; tree.RTO(1,null); tree.RTO(tree.root->sz,tree.root); Q[++tail] = tree.KT; while(head < tail) { node *fr = Q[++head]; if(fr->c[0] != null) Q[++tail] = fr->c[0]; if(fr->c[1] != null) Q[++tail] = fr->c[1]; Insert(fr);//此处吐血了一整天,上面的改回来了,这里却没改insert(root,fr); fr->who = type; } tree.KT = null; tree.root->c[1]->up(); tree.root->up(); } }spt[maxn]; void prepare() { null->id = 0; null->c[0] = null->c[1] = null->fa = NULL; null->sz = null->val = 0; null->gcd = -1; Type = 0; top = 0; } int main() { // freopen("input.txt","r",stdin); // freopen("cmp.txt","w",stdout); int t,m,ca=1,op,u,v,l,r,x; scanf("%d",&t); while(t--) { prepare(); scanf("%d%d",&n,&m); for(int i = 1; i <= n; i++){ spt[i].init(-1); spt[i].Insert(lim+1); } for(int i = 1,a; i <= n; i++) { scanf("%d",&a); spt[i].Insert(a); } int tot = 0; printf("Case #%d:\n",ca++); while(m--) { scanf("%d",&op); if(op == 1) { scanf("%d%d",&u,&v); node *tmp1 = ID[u+2*n] , *tmp2 = ID[v+2*n]; int tree1 = tmp1->who; int tree2 = tmp2->who; if(tree1 == tree2) continue; int sz1 = spt[tree1].root->sz; int sz2 = spt[tree2].root->sz; if(sz1 > sz2) { spt[tree1].Merge(spt[tree2]); } else { spt[tree2].Merge(spt[tree1]); } // if(spt[tree1].root->sz < 2 || spt[tree2].root->sz < 2){ // return 0; // break; // } // spt[tree1].debug(); } else if(op == 2) { scanf("%d%d",&u,&v); node *tmp1 = ID[u+2*n] , *tmp2 = ID[v+2*n]; int tree1 = tmp1->who; int tree2 = tmp2->who; // spt[tree1].debug(); spt[tree2].debug(); spt[tree1].Delete(tmp1); // if(spt[tree2].root->sz < 2) return 0; spt[tree2].Insert(tmp1); // spt[tree1].debug(); spt[tree2].debug(); } else if(op == 3) { scanf("%d%d",&u,&x); node *tmp = ID[u+2*n]; int tree = tmp->who; spt[tree].Change(u,x); } else if(op == 4) { scanf("%d",&u); node *tmp = ID[u+2*n]; int tree = tmp->who; printf("%d\n",spt[tree].Gao()); } else { scanf("%d%d%d",&u,&l,&r); node *tmp = ID[u+2*n]; int tree = tmp->who; // printf("id=%d tree=%d\n",tmp->id,tree); printf("%d\n",spt[tree].Solve(l,r)); } } } return 0; }