2018.11.18【LOJ120】持久化序列(可持久化非旋Treap)

传送门


解析:

(这句话仅针对指针)事实证明,在需要全局初始化的情况下,静态数组没有动态分配内存快。所以要么动态内存,要么静态内存动态初始化。

可持久化平衡树裸题,没什么好说的,我写的是非旋treap。

非旋treap的分裂关键字用大小考虑就行了。

不过听说这道题卡输入输出,建议加一个优化。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc put_char
#define cs const

namespace IO{
	cs int Rlen=1<<18|1;
	char buf[Rlen],*p1,*p2;
	char obuf[Rlen],*p3=obuf,*p4=obuf+Rlen;
	
	inline char get_char(){
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}	

	inline int getint(){
		re int num;
		re char c;
		while(!isdigit(c=gc()));num=c^48;
		while(isdigit(c=gc()))num=num*10+(c^48);
		return num;
	}
	
	inline void put_char(cs char &c){
		*p3++=c;
		if(p3==p4)fwrite(obuf,1,Rlen,stdout),p3=obuf;
	}
	
	inline void outint(ll a){
		static char ch[23];
		if(a==0)pc('0');
		while(a)ch[++ch[0]]=a-a/10*10,a/=10;
		while(ch[0])pc(ch[ch[0]--]^48);
	}
	
	inline void FLUSH(){
		if(p3==obuf)return ;
		fwrite(obuf,1,p3-obuf,stdout);
		p3=obuf;
	}
}
using namespace IO;

cs int N=300005;

typedef struct treap_node *point;
struct treap_node{
	point lc,rc;
	int val,siz,pri;
	treap_node(int _v=0):lc(NULL),rc(NULL),val(_v),pri(rand()),siz(1){}
	inline void pushup(){
		siz=(lc?lc->siz:0)+(rc?rc->siz:0)+1;
	}
};

inline point newnode(int _v=0){
	point p;
	p=(point)malloc(sizeof(treap_node));
	*p=treap_node(_v);
	return p;
}

typedef pair<point,point> data;

data split(point now,cs int &key){
	if(!now)return make_pair((point)NULL,(point)NULL);
	point p=(point)malloc(sizeof(treap_node));
	*p=*now;
	data res;
	if(key<=(now->lc?now->lc->siz:0)){
		res=split(now->lc,key);
		p->lc=res.second;
		p->pushup();
		return make_pair(res.first,p);
	}
	else{
		res=split(now->rc,key-(now->lc?now->lc->siz:0)-1);
		p->rc=res.first;
		p->pushup();
		return make_pair(p,res.second);
	}
}

point merge(point a,point b){
	if(!a)return b;
	if(!b)return a;
	point p=(point)malloc(sizeof(treap_node));
	if(a->pri>b->pri){
		*p=*a;
		p->rc=merge(a->rc,b);
	}
	else{
		*p=*b;
		p->lc=merge(a,b->lc);
	}
	p->pushup();
	return p;
}

point Insert(point now,cs int &pos,cs int &key){
	data res=split(now,pos-1);
	point tmp=newnode(key);
	return merge(merge(res.first,tmp),res.second);
}

point Delete(point now,cs int &pos){
	data res1=split(now,pos-1);
	data res2=split(res1.second,1);
	free(res2.first);
	return merge(res1.first,res2.second);
}

int queryKth(point now,cs int &pos){
	if(!now)return 0;
	if(pos==(now->lc?now->lc->siz:0)+1)return now->val;
	if(pos<=(now->lc?now->lc->siz:0))return queryKth(now->lc,pos);
	else return queryKth(now->rc,pos-(now->lc?now->lc->siz:0)-1);
}

point root[N];
int n,tot;
signed main(){
	srand(time(0));
	n=getint();
	while(n--){
		int op=getint(),t=getint(),pos=getint(),val;
		if(op==1)val=getint();
		switch(op){
			case 1:{
				root[++tot]=Insert(root[t],pos,val);
				break;
			}
			case 2:{
				root[++tot]=Delete(root[t],pos);
				break;
			}
			case 3:{
				outint(queryKth(root[t],pos));pc('\n');
				break;
			}
		}
	}
	FLUSH();
	return 0;
} 

转载于:https://www.cnblogs.com/zxyoi/p/10047088.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值