[AHOI2006]文本编辑器editor BZOIJ 1269

来源:互联网 发布:淘宝确认收货无法评价 编辑:程序博客网 时间:2024/06/06 04:56

题目意思没啥特点,意义明显,就是测试模板。


我的模板,真是烂爆炸了!!!!但是能用,勉强能用吧……不知道为啥这么慢,可能是我插入的时候偷懒采用一根链的方式插入的吧。(反正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;必须定义//必须在调用整个函数之前初始化outputnumvoid 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,后一个maxinline 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;}/*10Insert 13Balanced eertMove 2Delete 5NextInsert 7editorMove 0GetMove 11Rotate 4Get*/




0 0
原创粉丝点击