记录编号 23245 评测结果 AAAAAAAAAA
题目名称 [NOI 2003]文本编辑器 最终得分 100
用户昵称 Gravatar苏轼 是否通过 通过
代码语言 C 运行时间 1.243 s
提交时间 2011-03-04 20:03:49 内存使用 0.29 MiB
显示代码纯文本
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define ISLSON(X) ((X)==(X)->p->left)
#define ISRSON(X) ((X)==(X)->p->right)

typedef struct ST_SP_NODE {
	int size;
	char ch;
	struct ST_SP_NODE *p, *left, *right;
} SP_node;

typedef struct ST_SPTREE {
	struct ST_SP_NODE *NIL, *root;
} SP_tree;

FILE *fin, *fout;

void SP_init (SP_tree *tree)
{
	tree->NIL = malloc(sizeof(SP_tree));
	tree->root = tree->NIL->p = tree->NIL;
	tree->NIL->size = 0;
}

void SP_R_rotate (SP_tree *tree, SP_node *node)
{
	SP_node *l = node->left;

	l->p = node->p;
	if (node == tree->root)
		tree->root = l;
	else if (ISLSON(node))
		node->p->left = l;
	else
		node->p->right = l;

	node->p = l;
	node->left = l->right;
	l->right->p = node;
	l->right = node;

	l->size = node->size;
	node->size = node->left->size + node->right->size + 1;
}

void SP_L_rotate (SP_tree *tree, SP_node *node)
{
	SP_node *r = node->right;

	r->p = node->p;
	if (node == tree->root)
		tree->root = r;
	else if (ISLSON(node))
		node->p->left = r;
	else
		node->p->right = r;

	node->p = r;
	node->right = r->left;
	r->left->p = node;
	r->left = node;

	r->size = node->size;
	node->size = node->left->size + node->right->size + 1;
}

void SP_splay (SP_tree *tree, SP_node *node, SP_node *dest)
{
	while (node->p != dest)
	{
		if (node->p->p == dest)
		{
			if (ISLSON(node))
				SP_R_rotate(tree, node->p);
			else
				SP_L_rotate(tree, node->p);
		}
		else if (ISLSON(node))
		{
			if (ISLSON(node->p))
			{
				SP_R_rotate(tree, node->p->p);
				SP_R_rotate(tree, node->p);
			}
			else
			{
				SP_R_rotate(tree, node->p);
				SP_L_rotate(tree, node->p);
			}
		}
		else
		{
			if (ISRSON(node->p))
			{
				SP_L_rotate(tree, node->p->p);
				SP_L_rotate(tree, node->p);
			}
			else
			{
				SP_L_rotate(tree, node->p);
				SP_R_rotate(tree, node->p);
			}
		}
	}
}

SP_node *SP_prevnode (const SP_node *node)
{
	SP_node *pi = node->left;
	while (pi->size && pi->right->size)
		pi = pi->right;

	return pi;
}

SP_node *SP_succnode (const SP_node *node)
{
	SP_node *pi = node->right;
	while (pi->size && pi->left->size)
		pi = pi->left;

	return pi;
}

void SP_inserttree (SP_tree *tree, SP_node *curr,
					SP_node *node, const int l)
{
	if (!curr)
	{
		tree->root = node;
		tree->root->p = tree->NIL;
		return;
	}

	SP_splay(tree, curr, tree->NIL);
	SP_node *pi = tree->root->right, *pj = tree->root;

	tree->root->size += l;
	while (pi->size)
	{
		pj = pi;
		pi->size += l;
		pi = pi->left;
	}

	node->p = pj;
	if (pj != tree->root)
		pj->left = node;
	else
		pj->right = node;
}

void SP_freetree (SP_tree *tree, SP_node *node)
{
	if (node == tree->root)
		tree->root = tree->NIL;
	else
	{
		if (ISLSON(node))
			node->p->left = tree->NIL;
		else
			node->p->right = tree->NIL;

		SP_node *pi;
		for (pi=node->p; pi!=tree->NIL; pi=pi->p)
			pi->size = pi->left->size + pi->right->size +1;
	}

	free(node);
}

void SP_deleteall (SP_tree *tree, SP_node *l, SP_node *r)
{
	SP_splay(tree, l, tree->NIL);
	SP_node *pre = SP_prevnode(l);

	SP_splay(tree, r, tree->NIL);
	SP_node *suc = SP_succnode(r);

	if (pre != tree->NIL)
		SP_splay(tree, pre, tree->NIL);
	if (suc != tree->NIL)
		SP_splay(tree, suc, pre);

	if (suc != tree->NIL)
		SP_freetree(tree, suc->left);
	else if (pre != tree->NIL)
		SP_freetree(tree, pre->right);
	else
		SP_freetree(tree, tree->root);
}

SP_node *SP_find (SP_node *node, const int k)
{
	if (node->left->size + 1 == k)
		return node;
	else if (node->left->size >= k)
		return SP_find(node->left, k);
	else
		return SP_find(node->right, k-(node->left->size+1));
}

SP_node *str2spnode (const char *str, const int len, SP_node *NIL)
{
	SP_node *root = malloc(sizeof(SP_node)), *pi;
	int i;
	
	root->p = root->left = root->right = NIL;
	root->size = len;
	root->ch = str[0];

	pi = root;
	for (i=1; i<len; i++)
	{
		pi->right = malloc(sizeof(SP_node));
		pi->right->p = pi;
		pi = pi->right;

		pi->left = pi->right = NIL;
		pi->size = len-i;
		pi->ch = str[i];
	}
	
	return root;
}

void TRV_inorder (const SP_node *node)
{
	if (node->left->size)
		TRV_inorder(node->left);

	fputc(node->ch, fout);

	if (node->right->size)
		TRV_inorder(node->right);
}

int main ()
{
	fin = fopen("editor2003.in", "r"),
	fout = fopen("editor2003.out", "w");

	int T, i;
	SP_tree text;
	SP_node *curr;

	fscanf(fin, "%d", &T);

	SP_init(&text);
	SP_inserttree (&text, NULL, str2spnode("{", 1, text.NIL), 1);
	curr = text.root;
	SP_inserttree (&text, text.root, str2spnode("}", 1, text.NIL), 1);

	for (i=0; i<T; i++)
	{
		char cmd[50];
		int arg;
		fscanf(fin, "%s", cmd);
		
		switch (cmd[0])
		{
			while (fgetc(fin) != '\n') continue;
		
			case 'M':
			{
				fscanf(fin, "%d", &arg);
				curr = SP_find(text.root, arg + 1);
				SP_splay(&text, curr, text.NIL);
				break;
			}

			case 'I':
			{
				fscanf(fin, "%d", &arg);
				char *arg2 = malloc((arg+1)*sizeof(char)), *pi, c;

				pi = arg2;
				while (pi!=arg2+arg)
					if ((c = fgetc(fin)) >= 32)
						*(pi++) = c;

				SP_inserttree (&text, curr,
						str2spnode(arg2, arg, text.NIL), arg);
				break;
			}
	
			case 'D':
			{
				fscanf(fin, "%d", &arg);
				SP_node *pend = SP_find(curr, curr->left->size + arg + 1);
				SP_deleteall(&text, SP_succnode(curr), pend);
				break;
			}

			case 'G':
			{
				fscanf(fin, "%d", &arg);
				SP_node *pend = SP_find(text.root, curr->left->size + arg + 2);
				SP_splay(&text, curr, text.NIL);
				SP_splay(&text, pend, text.root);
				TRV_inorder(text.root->right->left);
				fputc('\n', fout);
				break;
			}

			case 'P':
			{
				curr = SP_prevnode(curr);
				SP_splay(&text, curr, text.NIL);
				break;
			}

			case 'N':
			{
				curr = SP_succnode(curr);
				SP_splay(&text, curr, text.NIL);
				break;
			}
		}
	}

	fclose(fin);
	fclose(fout);

	return 0;
}