题目意思没啥特点,意义明显,就是测试模板。
我的模板,真是烂爆炸了!!!!但是能用,勉强能用吧……不知道为啥这么慢,可能是我插入的时候偷懒采用一根链的方式插入的吧。(反正splay会自己调整……理论实践不会TLE才对啊~~~~)
#include <cstdio> #include <cstring> #include <vector> #include <cstdlib> #include <iostream> #include <cmath> using namespace std; const int maxint=~0U>>1; /* splay,各个节点之间需要传递的信息 */ struct mark { bool reverse; //这个节点的所有子节点是否要颠倒 /* bool b; bool a; 表示a,b表示一些需要传递的参数,比如是否要倒置之类,或者区间加上一直值,减去一个值 */ mark() { reverse=0; } //1要颠倒 0不要颠倒 }; vector<int>outputnum; /* splay的节点信息 */ struct node { int key; int size; mark cd; node *c[2]; node():key(0),size(0){c[0]=c[1]=this;} node(int key_,node* c0_,node* c1_): key(key_){c[0]=c0_;c[1]=c1_;} node* rz(){return size=c[0]->size+c[1]->size+1,this;} } Tnull,*null=&Tnull; struct splay { node *root; splay() /*初始化 不需要做任何修改*/ { root=(new node(*null))->rz(); root->key=maxint; } /*把k节点的信息,传递到k节点的两个儿子,同时,如果是逆转操作,左右儿子 * 需要进行交换位置。 【只传递给两个儿子!】 * do_reversal有自动判断,当前node是否有信息要传递的功能 */ void do_reversal(node* k) { if (k -> cd.reverse)//如果这个节点需要传递 { k -> cd.reverse = 0; //标记为已经传递,标记下传,并且交换 swap(k -> c[0], k -> c[1]);//左右儿子交换 if (k -> c[0] != null) k -> c[0] -> cd.reverse ^= 1; if (k -> c[1] != null) k -> c[1] -> cd.reverse ^= 1; } } /* * 从根节点把信息,向下传递2层 */ void check() { do_reversal(root);//根的左右儿子逆转,先把根的信息处理完,do_reversal会自动判断当前节点是否要做操作 //然后判断,根的左右儿子是否有信息要传递 if (root -> c[0] != null) do_reversal(root -> c[0]); if (root -> c[1] != null) do_reversal(root -> c[1]); } //zig,zigzig,finish,select操作,全部和key无关,不需要做任何修改 void zig(bool d) { node *t=root->c[d]; root->c[d]=null->c[d]; null->c[d]=root; root=t; } void zigzig(bool d) { node *t=root->c[d]->c[d]; root->c[d]->c[d]=null->c[d]; null->c[d]=root->c[d]; root->c[d]=null->c[d]->c[!d]; null->c[d]->c[!d]=root->rz(); root=t; } void finish(bool d) { node *t=null->c[d],*p=root->c[!d]; while(t!=null) { t=null->c[d]->c[d]; null->c[d]->c[d]=p; p=null->c[d]->rz(); null->c[d]=t; } root->c[!d]=p; } void select(int k) //第k+1个元素旋转到根,也就是有k个数字比要找的数字小 { int t; while(1) { check(); bool d=k>(t=root->c[0]->size); if(k==t||root->c[d]==null)break; if(d)k-=t+1; bool dd=k>(t=root->c[d]->c[0]->size); if(k==t||root->c[d]->c[dd]==null){zig(d);break;} if(dd)k-=t+1; d!=dd?zig(d),zig(dd):zigzig(d); } finish(0),finish(1); root->rz();//更新根节点的size } /* pg(node k); 打印整棵树,包括左右儿子信息,size,传递的参数 通常直接调用 pg(*root) 即可 */ void pg(node k)//打印这棵树 { cout<<k.key<<" [left son:"; if (k.c[0] != null) cout<<k.c[0] -> key; else cout<<"none"; cout<<"] [right son:"; if (k.c[1] != null) cout<< k.c[1] -> key; else cout<<"none"; cout<<"] [size ="; cout<<k.size<<"]" <<"逆转否?"<<" "<<k.cd.reverse<<"\n"; if (k.c[0] != null) pg(*k.c[0]); if (k.c[1] != null) pg(*k.c[1]); } /* * 输出这棵树的中序遍历,包括-maxint,和+maxin * 调用方式通常直接为zhongxu(root) */ void zhongxu(node* k) { do_reversal(k);//根的左右儿子逆转 if (k -> c[0] != null) do_reversal(k -> c[0]); if (k -> c[1] != null) do_reversal(k -> c[1]); if (k -> c[0] != null) zhongxu(k -> c[0]); cout<<(char)k -> key<<" "; if (k -> c[1] != null) zhongxu(k -> c[1]); } // vector<int>outputnum;必须定义 // 必须在调用整个函数之前初始化outputnum void get_output_info(node* k) { do_reversal(k);//根的左右儿子逆转 if (k -> c[0] != null) do_reversal(k -> c[0]); if (k -> c[1] != null) do_reversal(k -> c[1]); if (k -> c[0] != null) get_output_info(k -> c[0]); outputnum.push_back(k -> key); if (k -> c[1] != null) get_output_info(k -> c[1]); } void output()//输出全部元素,除了-max和+max { outputnum.clear(); get_output_info(root); for (int i = 1; i != outputnum.size() - 2; ++ i) printf("%d ", outputnum[i]); printf("%d\n", outputnum[outputnum.size() - 2]); } void output(int left, int right) //把(left到right)区间的元素输出 { outputnum.clear(); transformation(left, right); get_output_info(root -> c[1] -> c[0]); //cout<<outputnum.size()<<endl; for (int i = 0; i != outputnum.size() - 1; ++ i) printf("%d ", outputnum[i]); printf("%c\n", outputnum[outputnum.size() - 1]); } /////////////////////////////////////// node* init(int x[], int n)//形成一颗初始树, 有n个元素,下标从1开始的数组 { //因为是初始化,所以先添加了一个最小的节点-maxint进这棵树 root -> c[0] = (new node(-maxint, null, null)) -> rz();//左儿子插入一个新元素 root -> rz(); for (int i = 1; i <= n; ++ i) { transformation(i, i + 1); root -> c[1] -> c[0] = (new node(x[i], null, null)) -> rz(); root -> c[1] -> rz(); root -> rz(); } return root; } node* init_no_maxint(int x[], int n)//同上,但是不添加-maxint,和max进这棵树,这是为了方便合并 { root -> c[0] = (new node(x[1], null, null)) -> rz();//左儿子插入一个新元素 root -> rz(); for (int i = 2; i <= n; ++ i) { transformation(i - 1, i); root -> c[1] -> c[0] = (new node(x[i], null, null)) -> rz(); root -> c[1] -> rz(); root -> rz(); } transformation(n, n + 1); delete root -> c[1]; root -> c[1] = null; return root -> rz(); } /* * clear()以下为删除把整个splay清空为初始化状态 */ void dfs_clear(node *k) { if (k -> c[0] != null) { dfs_clear(k -> c[0]); delete (k -> c[0]); } if (k -> c[1] != null) { dfs_clear(k -> c[1]); delete k -> c[1]; } } node* clear() //删除整棵树,只留下一个maxint在树中 { int allsize = root -> size; select(allsize - 1); dfs_clear(root); root -> c[0] = root -> c[1] = null; return root; } /* * 把第left个节点旋转到根,right为根的右儿子 * 也就是提取区间[left+1,right-1] * 当然,这里包括-maxint, maxint这2个节点 */ node* transformation(int left, int right) { select(left - 1); node *oldroot = root; root = root -> c[1]; select(right -left - 1); node *t = root; root = oldroot; root -> c[1] = t; return root -> rz(); } /* * 把[left+1, right -1]之间的东西倒置 */ node* reversal(int left, int right) // (left,right)之间要倒置,不包含left,right { transformation(left, right); root -> c[1] -> c[0] -> cd.reverse ^= 1; return root; } int sel(int k){return select(k-1),root->key;} //第k名的是谁 } sp; struct interval// 形成区间的一个splay { splay core;//包含头一个-max,后一个max inline int size() { return core.root -> size - 2; } inline void output() { core.output(); } void output(int left, int right)//输出left 到right区间的元素 { right += 2; core.output(left, right); } inline void clear() { core.clear(); } inline void init(int x[], int n)//初始化,给core里初始值 //下标从1开始,一共n个元素! { core.init(x, n); } /* * 第left个元素,到第right个元素,全部倒转 */ void daozhuan(int left, int right) { right += 2; core.reversal(left, right); } /* * 按照顺序输出所有元素,注意,这里会让所有传递信息进行传递! */ void output_all_element() { core.zhongxu(core.root); cout<<endl; } node* delete_qujian(int left, int right) { right += 2; core.transformation(left, right); node *ret = core.root -> c[1] -> c[0]; core.root -> c[1] -> c[0] = null; core.root -> c[1] -> rz(); core.root -> rz(); return ret; } void insert_node(node *newinter, int k)//在区间[1,k],[k+1,n]之间插入 { ++k; //因为存在-max的元素,所以区间都要后置一点 core.transformation(k, k + 1); core.root -> c[1] -> c[0] = newinter; } /* * 在第k个元素后面插入n个元素,n个元素保存在x[1..n]中。 下标为1开始 */ void insert(int x[], int n, int k) { splay tmp; node *tmproot = tmp.init_no_maxint(x, n); insert_node(tmproot, k); } }qujian; int x[2000000]; int main() { int t, guangbiao=0; scanf("%d", &t); char s[100], ch; qujian.init(x,0); while (t--) { scanf("%s", s); if (strcmp(s, "Insert") == 0) { int n; scanf("%d", &n); getchar(); for (int i = 1; i <= n; ++ i) { ch = getchar(); x[i] = ch; } qujian.insert(x, n, guangbiao); } if (strcmp(s, "Move") == 0) { scanf("%d", &guangbiao); } if (strcmp(s, "Delete") == 0) { int n; scanf("%d", &n); qujian.delete_qujian(guangbiao + 1, guangbiao + n); } if (strcmp(s, "Rotate") == 0) { int n; scanf("%d", &n); qujian.daozhuan(guangbiao + 1, guangbiao + n); } if (strcmp(s, "Get") == 0) { qujian.output(guangbiao + 1, guangbiao + 1); } if (strcmp(s, "Prev") == 0) { --guangbiao; } if (strcmp(s, "Next") == 0) { ++guangbiao; } } return 0; } /* 10 Insert 13 Balanced eert Move 2 Delete 5 Next Insert 7 editor Move 0 Get Move 11 Rotate 4 Get */