UVA-11996-Jewel Magic(FHQTreap版)

题目链接:UVA-11996-Jewel Magic

题目大意:
给你一个 01 01 01序列,要求支持一下四个操作

输入操作
1 1 1 p p p c c c在数列第 p p p个数字之后插入 c c c
2 2 2 p p p删除第 p p p个位置的元素
3 3 3 p 1 p_1 p1 p 2 p_2 p2将第 p 1 p_1 p1到第 p 2 p_2 p2个元素之间的元素翻转
4 4 4 p 1 p_1 p1 p 2 p_2 p2输出第以 p 1 p_1 p1开始和以 p 2 p_2 p2开始的串的 L C P LCP LCP

多组数据 n , m ≤ 200000 n,m\leq200000 n,m200000

题目分析:
如果只看前三个操作,就是普通的伸展树的操作,而对于最后一个求 L C P LCP LCP,由于有修改的操作,并不好用后缀数组维护,考虑二分 H a s h Hash Hash,由于有翻转的存在,需要同时维护一段 01 01 01 序列的前缀 H a s h Hash Hash 和后缀 H a s h Hash Hash ,然后就可以维护伸展树的操作了。

题目代码:(FHQTreap版)

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<time.h>
#define mxn 400005
#define LL long long
using namespace std;
int rt,sz,arr[mxn];
LL _pow[mxn];
char str[mxn];
struct Node{
	int size,val,pri,tag;
	int lson,rson;
	LL hashl,hashr;
}T[mxn];
int new_node(int v){
	T[++sz].val=v;
	T[sz].size=1;
	T[sz].hashl=T[sz].hashr=v*3;
	T[sz].rson=T[sz].rson=T[sz].tag=0;
	T[sz].pri=rand();
	return sz;
}
void reverse(int k){
	if(!k)return;
	swap(T[k].lson,T[k].rson);
	swap(T[k].hashl,T[k].hashr);
	T[k].tag^=1;
}
void pushdown(int k){
	if(!k)return;
	if(T[k].tag){
		reverse(T[k].lson);
		reverse(T[k].rson);
		T[k].tag=0;
	}
}
void pushup(int k){
	if(!k)return;
	T[k].size=T[T[k].lson].size+T[T[k].rson].size+1;
	T[k].hashl=T[T[k].lson].hashl+(T[T[k].rson].hashl)*_pow[T[T[k].lson].size+1]+
	_pow[T[T[k].lson].size+1]*T[k].val;
	T[k].hashr=T[T[k].rson].hashr+(T[T[k].lson].hashr)*_pow[T[T[k].rson].size+1]+
	_pow[T[T[k].rson].size+1]*T[k].val;
}
void split(int now,int k,int &x,int &y){
	if(!now){x=y=0;return;}
	else{
		pushdown(now);
		if(k<=T[T[now].lson].size)
			y=now,split(T[now].lson,k,x,T[now].lson);
		else x=now,split(T[now].rson,k-T[T[now].lson].size-1,T[now].rson,y);
		pushup(now);
	}
}
int merge(int x,int y){
	if(!x||!y)return x+y;
	if(T[x].pri<T[y].pri){
		pushdown(x);
		T[x].rson=merge(T[x].rson,y);
		pushup(x);
		return x;
	}
	else{
		pushdown(y);
		T[y].lson=merge(x,T[y].lson);
		pushup(y);
		return y;
	}
}
int build(int l,int r){
	if(l==r)return new_node(arr[l]);
	int mid=(l+r)>>1;
	int x=build(l,mid),y=build(mid+1,r);
	return merge(x,y);
}
int main()
{
	srand(time(0));
	int n,m;
	_pow[0]=1;
	for(int i=1;i<=mxn-5;i++)
		_pow[i]=_pow[i-1]*3;
	while(scanf("%d %d",&n,&m)!=EOF){
		for(int i=1;i<=mxn-5;i++){
			T[i].hashl=T[i].hashr=0;
			T[i].lson=T[i].rson=0;
			T[i].pri=T[i].size=T[i].tag=T[i].val=0;
		}
		sz=0;rt=0;
		scanf("%s",str);
		for(int i=1;i<=n;i++)
			arr[i]=str[i-1]-'0';
		rt=build(1,n);
		for(int i=1;i<=m;i++){
			int opt,p,q,c,x,y,z;
			scanf("%d",&opt);
			if(opt==1){
				scanf("%d %d",&p,&c);
				split(rt,p,x,y);
				x=merge(x,new_node(c));
				rt=merge(x,y);
			}
			if(opt==2){
				scanf("%d",&p);
				split(rt,p-1,x,y);
				split(y,1,y,z);
				rt=merge(x,z);
			}
			if(opt==3){
				scanf("%d %d",&p,&q);
				split(rt,p-1,x,y);
				split(y,q-p+1,y,z);
				reverse(y);
				y=merge(y,z);
				rt=merge(x,y);
			}
			if(opt==4){
				scanf("%d %d",&p,&q);
				int L=0,R=T[rt].size-max(p,q)+1,ans,flag=0;
				while(L<=R){
					int mid=(L+R)>>1;
					split(rt,p-1,x,y);
					split(y,mid,y,z);
					int qz1=T[y].hashl;
					y=merge(y,z);
					rt=merge(x,y);
					split(rt,q-1,x,y);
					split(y,mid,y,z);
					int qz2=T[y].hashl;
					y=merge(y,z);
					rt=merge(x,y);
					if(qz1==qz2)ans=mid,L=mid+1;
					else R=mid;
					if(L==R&&!flag){flag=1;continue;}
					if(L==R&&flag)break;
				}
				printf("%d\n",ans);
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值