记录编号 377853 评测结果 AAAAAAAAAA
题目名称 2623.[HZOI 2016][GDOI2016模拟3.14] hashit 最终得分 100
用户昵称 半汪 是否通过 通过
代码语言 C++ 运行时间 0.376 s
提交时间 2017-03-02 16:44:04 内存使用 3.18 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned int TYPE;
const int maxn=100010;
const TYPE H=10000007;
const ll e=(1ll<<61);
int son[maxn][2],hkey[maxn],Rt,N=0,goat=0;
TYPE hash[maxn],POW[maxn];
ll tag[maxn],ans=0,nowl,nowr;
char ch[maxn],s[maxn];
#define L(x) son[x][0]
#define R(x) son[x][1]
void rebuild(int x,ll l,ll r){
	if(!x)return;
	ll mid=(l+r)/2;
	tag[x]=mid;
	rebuild(L(x),l,mid);rebuild(R(x),mid,r);
}
int rotate(int x,int k,ll l,ll r){
	int y=son[x][k^1];
	son[x][k^1]=son[y][k];
	son[y][k]=x;
	rebuild(y,l,r);
	return y;
}
int rotate(int x,int k){
	int y=son[x][k^1];
	son[x][k^1]=son[y][k];
	son[y][k]=x;
	return y;
}
bool dcmp(int x,int y){
	return (s[x]<s[y]||(s[x]==s[y]&&tag[x-1]<tag[y-1]));
}
bool check(int x,int y,int mid){
	return (hash[x]-hash[x-mid]*POW[mid])==(hash[y]-hash[y-mid]*POW[mid]);
}
int LCP(int x,int y){
	int l=1,r=min(x,y),maxx=0;
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(x,y,mid)){
			l=mid+1;maxx=max(maxx,mid); 
		} 
		else r=mid-1;
	}
	return maxx;
}
int query_pre(int x){
	int now=Rt,id=0;
	while(now){
		if(dcmp(now,x)){
			if(!id||tag[now]>tag[id])id=now;
			now=R(now);
		}
		else now=L(now);
	}
	return id;
}
int query_scn(int x){
	int now=Rt,id=0;
	while(now){	
		if(dcmp(x,now)){
			if(!id||tag[now]<tag[id])id=now;
			now=L(now);
		}
		else now=R(now);
	}
	return id;
}
int erase(int rt,int x,ll l,ll r){
	ll mid=(l+r)/2;
	if(rt==x){
		if(!L(rt)){
			rebuild(R(rt),l,r);
			return R(rt);
		}
		if(!R(rt)){
			rebuild(L(rt),l,r);
			return L(rt);
		}
		if(hkey[L(rt)]<hkey[R(rt)])rt=rotate(rt,1),R(rt)=erase(R(rt),x,mid,r);
		else rt=rotate(rt,0),L(rt)=erase(L(rt),x,l,mid);
		goat=rt;nowl=l;nowr=r;
	}
	else if(tag[rt]<tag[x])R(rt)=erase(R(rt),x,mid,r);
	else L(rt)=erase(L(rt),x,l,mid);
	return rt;
}
void insert(int &rt,int x,ll l,ll r){
	if(!rt){
		rt=x;tag[x]=(l+r)/2;L(rt)=R(rt)=0;hkey[rt]=rand()%10000000+1;
		return;
	}
	ll mid=(l+r)/2;
	if(dcmp(x,rt))insert(L(rt),x,l,mid);
	else insert(R(rt),x,mid,r);
	if(L(rt)&&hkey[L(rt)]<hkey[rt])rt=rotate(rt,1,l,r);
	else if(R(rt)&&hkey[R(rt)]<hkey[rt])rt=rotate(rt,0,l,r);
}
void check(){
	cout<<"root"<<Rt<<endl;
	for(int i=1;i<=N;i++)cout<<i<<" "<<tag[i]<<" "<<L(i)<<" "<<R(i)<<endl;
}
void Erase(int x){
	int pre=query_pre(x),scn=query_scn(x);
	int h1=0,h2=0;
	if(pre)h1=LCP(pre,x);if(scn)h2=LCP(scn,x);
	ans-=(ll)x-max(h1,h2);
	goat=0;
	Rt=erase(Rt,x,0,e);
	if(goat)rebuild(goat,nowl,nowr);
	printf("%lld\n",ans);
}
void Add(int x,char a){
	s[x]=a;
	hash[x]=hash[x-1]*H+a-'a';
	int pre=query_pre(x),scn=query_scn(x);
	int h1=0,h2=0;
	if(pre)h1=LCP(pre,x);if(scn)h2=LCP(scn,x);
	ans+=(ll)x-max(h1,h2);
	insert(Rt,x,0,e);
	printf("%lld\n",ans);
}
int main(){
	srand(121212);
	freopen("hahaha.in","r",stdin);freopen("hahaha.out","w",stdout);
	int M;
	scanf("%d",&M);
	POW[0]=1;
	for(int i=1;i<=M;i++)POW[i]=POW[i-1]*H;
	scanf("%s",ch+1);
	for(int i=1;i<=M;i++){
		if(ch[i]=='-'){
			Erase(N);
			N--;
		}
		else Add(++N,ch[i]);
	}
     return 0;
 }