[AHOI2006]文本编辑器editor BZOIJ 1269

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


我的模板,真是烂爆炸了!!!!但是能用,勉强能用吧……不知道为啥这么慢,可能是我插入的时候偷懒采用一根链的方式插入的吧。(反正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

*/




你可能感兴趣的:([AHOI2006]文本编辑器editor BZOIJ 1269)