hdu 4680 About set 小記(畢竟是一天的時光啊)
阿新 • • 發佈:2019-02-18
/* ********************************************** 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; 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; bool d() { return fa->c[0] == this; } void setc(int d,node *s) { c[d] = s; s->fa = this; } void up() { sz = c[0]->sz + c[1]->sz + 1; gcd = GCD(c[0]->gcd,c[1]->gcd); gcd = GCD(gcd,val); } 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; 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(); } 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; } } 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); } 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; } void init(int v) { root = new_node(null,v); type = ++Type; root->who = type; } 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(); } void Delete(node *x) { Splay(x,null); Del_root(); } void Insert(node *x) { x->clear(null); //插入一個節點前不能忘記清空它的左右兒子 insert(root,x); Splay(x,null); x->who = type; } 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(); } 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) { // equal or bigger than 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); } } node *find_pre(node *x,int v) { // strictly less than 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); } } 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(root,a+b)->val; if(c > lim || c == -1) break; a = b; b = c; ans++; } return ans; } int Solve(int l,int r) { node *pre = find_pre(root,l); node *succ = find_succ(root,r+1); 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() { 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); node *tmp = spt[i].new_node(null,lim+1); spt[i].Insert(tmp); } for(int i = 1,a; i <= n; i++) { scanf("%d",&a); node *tmp = spt[i].new_node(null,a); spt[i].Insert(tmp); } 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]); } } 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].Delete(tmp1); spt[tree2].Insert(tmp1); } 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("%d\n",spt[tree].Solve(l,r)); } } } return 0; }