bzoj 1014伸展树 模板题

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
using  namespace std;
long long wei[100010];
char s[100010];
int n;
void init()//这是针对本题的操作并无通用性
{
	wei[0] = 1;
	for (int i = 1; i < 100010; i++)
	{
		wei[i] = (wei[i - 1] * 26) % 2333333333;
	}
}
//写splaytree的时候关键是要和0点撇清关系。。。
struct splaytree//从这开始是splay 模板
{
	int fa, son[2], size, worth,num;
	unsigned long long value;
	splaytree()
	{
		fa = son[0] = son[1] = size = worth = value = 0;
	}
};
splaytree node[250010];
void update(splaytree &k)
{
	k.size = 1 + node[k.son[0]].size + node[k.son[1]].size;
	k.value =(k.worth*wei[node[k.son[0]].size] + node[k.son[0]].value + node[k.son[1]].value*wei[node[k.son[0]].size + 1]) % 2333333333;
}
int link(splaytree &k, int d, int kid)
{
	k.son[d] = kid;
	if (kid)//撇清关系
		node[kid].fa =k.num;
	return k.num;
}
int getlr(splaytree &k)
{
		return node[k.fa].son[1] ==k.num;
}
int tot = 0;
int root;
int newnode(int worth)
{
	tot++;
	node[tot].worth = node[tot].value = worth;
	node[tot].size = 1;
	node[tot].num = tot;
	return tot;
}
void rot(int x)
{
	int fa = node[x].fa;
	int gfa = node[fa].fa;
	int dx = getlr(node[x]);
	int dfa =getlr(node[fa]);
	link(node[x],dx ^ 1,link(node[fa],dx, node[x].son[dx ^ 1]));
	if (gfa)
		link(node[gfa],dfa, x);
	else
		node[x].fa = gfa;
	update(node[fa]);
}
void newsplay(int x,int to)
{
	while (node[x].fa&&node[x].fa!=to)//这易错因为node[x].fa又阔能为空然后to不空这样就有bug 了。。。
	{
		if (node[node[x].fa].fa!=to)
			getlr(node[node[x].fa]) == getlr(node[x]) ? rot(node[x].fa) : rot(x);
		rot(x);
	}
	update(node[x]);
	if(to==0)
	root = x;//这是易错的,因为如果不是转到root是不能修改root的
}
int build(int l, int r)
{
	//cout << "sds" << endl;
	if (l > r)
		return 0;
	int mid = (l + r) >> 1;
	int num = newnode(s[mid]-'a');
	link(node[num],0, build(l, mid - 1));
	link(node[num],1, build(mid + 1, r));
	update(node[num]);
	if (l == 0 && r == n)
		root = num;
	return num;
}
int find(int size)
{
	int temp = root;
	while (temp != 0)
	{
		if (node[node[temp].son[0]].size >= size)
			temp = node[temp].son[0];
		else
		{
			size -= node[node[temp].son[0]].size;
			if (size == 1)return temp;
			size--;
			temp = node[temp].son[1];
		}
	}
	return 0;
}//这结束模板
void insert(int pos,char kid)//以下是针对本题的操作
{
	int kidnum = newnode(kid - 'a');
	if (pos == 0 || pos == node[root].size)
	{
		int k;
		pos == 0 ? (k = find(1)) : (k = find(node[root].size));
		newsplay(k, 0);
		pos == 0 ? link(node[k],0, kidnum) : link(node[k],1, kidnum);
		update(node[k]);
	}
	else
	{
		int l = pos;
		int r = pos + 1;
		int nodel = find(l);
		int noder = find(r);
		newsplay(nodel, 0);
		newsplay(noder, root);
		link(node[noder],0, kidnum);
		for (int i = noder; i != 0; i = node[i].fa)
		update(node[i]);
	}
}
unsigned long long findvalue(int l, int r)
{
	if (l == 1&&r!=node[root].size)
	{
		int end = find(r + 1);
		newsplay(end, 0);
		return node[node[root].son[0]].value;
	}
	if (r == node[root].size&&l!=1)
	{
		int begin = find(l - 1);
		newsplay(begin, 0);
		return node[node[root].son[1]].value;
	}
	if (l == 1 && r == node[root].size)
	{
		return node[root].value;
	}
	l = find(l - 1);
	r = find(r +1);
	newsplay(l, 0);
	newsplay(r, root);
	return node[node[r].son[0]].value;
}
int com(int first, int second)
{
	int l = 0;
	int r = min(node[root].size - first + 1, node[root].size - second + 1);
	int mid = r;
	//cout << "r:" << r << " " << "l:" << l << endl;
	while ((r-l)>1)
	{
		unsigned long long p1 = findvalue(first, first + mid - 1);
		unsigned long long p2 = findvalue(second, second + mid - 1);
		if (p1 == p2)
			l = mid;
		else
			r = mid - 1;
		mid = (l + r) >> 1;
	}
	unsigned long long p1 = findvalue(first, first + r- 1);
	unsigned long long p2 = findvalue(second, second + r - 1);
	if (p1 != p2)
		return l;
	else
		return r;
}
void change(int pos, char worth)
{
	pos = find(pos);
	node[pos].worth = worth - 'a';
	update(node[pos]);
	newsplay(pos, 0);
}
int main()
{
	int i;
	for ( i = 0;; i++)
	{
		scanf("%c", &s[i]);
		if (s[i] == '\n')
			break;
	}
	n = i - 1;
	init();
	build(0, n);
	int m;
	scanf("%d", &m);
	for (int i = 0; i < m; i++)
	{
	//	cout << i << endl;
		char c;
		 getchar();
		scanf("%c", &c);
		if (c == 'Q')
		{
			int l, r;
			scanf("%d%d", &l, &r);
			int ans = com(l, r);
			printf("%d\n", ans);
		}
		if (c == 'R')
		{
			int l;
			char c;
			scanf("%d", &l);
			getchar();
			scanf("%c", &c);
			change(l, c);
		}
		if (c == 'I')
		{
			int l;
			char c;
			scanf("%d", &l);
			getchar();
			scanf("%c", &c);
			insert(l, c);
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值