[luogu3835]可持久化平衡树

就是把普通平衡树的代码可持久化一下

第一发90,最后两个点MLE???这是什么操作

后来把能非递归的都改成非递归,结果TLE???这又是什么操作

最后发现我才用了内存限制的一半,改大一点之后过掉倒数第二个点,再改大一点就A掉了

所以TLE是什么鬼啊

之前立了个用指针的flag,结果这题指针版会MLE......

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int l[25000000],r[25000000],v[25000000],siz[25000000],fix[25000000],rt[500010],stk[500010],top,tot;
void update(int x){siz[x]=siz[l[x]]+siz[r[x]]+1;}
struct pair{
	int l,r;
	pair(int a=0,int b=0){l=a;r=b;}
};
int newnode(int d){
	int x;
	if(top){
		x=stk[top];
		top--;
	}else
		x=++tot;
	v[x]=d;
	l[x]=r[x]=0;
	siz[x]=1;
	fix[x]=rand()*rand();
	return x;
}
int copy(int u){
	int x;
	if(top){
		x=stk[top];
		top--;
	}else
		x=++tot;
	v[x]=v[u];
	l[x]=l[u];
	r[x]=r[u];
	siz[x]=siz[u];
	fix[x]=fix[u];
	return x;
}
pair split(int x,int k){
	if(x==0)return pair();
	if(k==0)return pair(0,copy(x));
	if(k==siz[x])return pair(copy(x),0);
	pair s;
	int n=copy(x);
	if(k<=siz[l[x]]){
		s=split(l[n],k);
		l[n]=s.r;
		s.r=n;
	}else{
		s=split(r[n],k-siz[l[x]]-1);
		r[n]=s.l;
		s.l=n;
	}
	update(n);
	return s;
}
int merge(int x,int y){
	if(x==0&&y==0)return 0;
	if(x==0)return copy(y);
	if(y==0)return copy(x);
	int n;
	if(fix[x]<fix[y]){
		n=copy(x);
		r[n]=merge(r[n],y);
	}else{
		n=copy(y);
		l[n]=merge(x,l[n]);
	}
	update(n);
	return n;
}
bool find(int x,int d){
	while(x){
		if(d==v[x])return 1;
		if(d<v[x])
			x=l[x];
		else
			x=r[x];
	}
	return 0;
}
int lt(int x,int d){
	int s=0;
	while(x){
		if(d<=v[x])
			x=l[x];
		else{
			s+=siz[l[x]]+1;
			x=r[x];
		}
	}
	return s;
}
int getkth(int x,int k){
	while(k!=siz[l[x]]+1){
		if(k<=siz[l[x]])
			x=l[x];
		else{
			k-=siz[l[x]]+1;
			x=r[x];
		}
	}
	return v[x];
}
#define inf 2147483647
int presc(int x,int d){
	int ans=-inf;
	while(x){
		if(v[x]<d){
			ans=v[x];
			x=r[x];
		}else
			x=l[x];
	}
	return ans;
}
int nexsc(int x,int d){
	int ans=inf;
	while(x){
		if(v[x]>d){
			ans=v[x];
			x=l[x];
		}else
			x=r[x];
	}
	return ans;
}
int main(){
	srand(time(0));
	int i,m,v,o,x;
	pair s,t;
	scanf("%d",&m);
	for(i=1;i<=m;i++){
		scanf("%d%d%d",&v,&o,&x);
		if(o==1){
			s=split(rt[v],lt(rt[v],x));
			rt[i]=merge(s.l,merge(newnode(x),s.r));
		}
		if(o==2){
			if(find(rt[v],x)){
				s=split(rt[v],lt(rt[v],x));
				t=split(s.r,1);
				rt[i]=merge(s.l,t.r);
				top++;
				stk[top]=t.l;
			}else
				rt[i]=rt[v];
		}
		if(o==3){
			printf("%d\n",lt(rt[v],x)+1);
			rt[i]=rt[v];
		}
		if(o==4){
			printf("%d\n",getkth(rt[v],x));
			rt[i]=rt[v];
		}
		if(o==5){
			printf("%d\n",presc(rt[v],x));
			rt[i]=rt[v];
		}
		if(o==6){
			printf("%d\n",nexsc(rt[v],x));
			rt[i]=rt[v];
		}
	}
}
时间: 2024-10-25 20:26:55

[luogu3835]可持久化平衡树的相关文章

[rope大法好] STL里面的可持久化平衡树--rope

简单用法: #include <ext/rope> using namespace __gnu_cxx; int a[1000]; rope<int> x; rope<int> x(a,a + n); rope<int> a(x); x->at(10); x[10]; x->push_back(x) // 在末尾添加x x->insert(pos,x) // 在pos插入x x->erase(pos,x) // 从pos开始删除x个

洛谷P3835 【模板】可持久化平衡树

题目背景 本题为题目 普通平衡树 的可持久化加强版. 数据已经经过强化 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本): 插入x数 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作) 查询x数的排名(排名定义为比当前数小的数的个数+1.若有多个相同的数,因输出最小的排名) 查询排名为x的数 求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647) 求x的后继(后继定义为大于x,且最小的数,如不存在

Luogu P3835 【模板】可持久化平衡树

P3835 [模板]可持久化平衡树 题意 题目背景 本题为题目普通平衡树的可持久化加强版. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本): 插入\(x\)数 删除\(x\)数(若有多个相同的数,因只删除一个,如果没有请忽略该操作) 查询\(x\)数的排名(排名定义为比当前数小的数的个数\(+1\).若有多个相同的数,因输出最小的排名) 查询排名为x的数 求\(x\)的前驱(前驱定义为小于\(x\),且最大的数,如不存在输出\(-2

【模板】可持久化平衡树

题目背景 本题为题目 普通平衡树 的可持久化加强版. 数据已经经过强化 感谢@Kelin 提供的一组hack数据 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本): 插入x数 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作) 查询x数的排名(排名定义为比当前数小的数的个数+1.若有多个相同的数,因输出最小的排名) 查询排名为x的数 求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647) 求x的后

可持久化平衡树详解及实现方法分析

目录 前置要求 核心思想 实现方法比较:指针 与 数组模拟指针 Merge 是否应该新建节点 参考程序 前置要求 带旋转的平衡树会改变祖先关系,这令可持久化变得困难.所以需要使用非旋的平衡树,如非旋treap.本文以非旋treap为例. 核心思想 可持久化的数据结构,其核心都是不改变历史的信息.当需要对信息进行修改的时候就新开一个节点,继承历史信息,然后再进行修改. 对于非旋treap来说,主要是对 Split 和 Merge 两个操作进行可持久化.剩下的操作不会对数据产生影响.而考虑到非旋tr

洛谷 P3835 【模板】可持久化平衡树

这个题也是可以用可持久化线段树来解决的. 值域线段树(也有的叫权值线段树)可以用来维护一个可重集,并实现一些一般情况下平衡树才能实现的事情. 如果用值来当做区间左右端点,每个叶子节点上存某个值出现的次数,非叶子节点上存一定范围内的值出现的总次数,就可以建成值域线段树.可以在上面直接查询第k大值.小于某值的数的个数等等,具体请百度或参见代码. 如何将线段树可持久化呢?线段树在单点更新的时候会经过log n个节点,每一次更新时显然也只有这么多节点会发生变化. 记录每一个版本的线段树的根节点,每一次操

可持久化平衡树

可持久化普通平衡树 题意 如题. 解法 大家都知道,用权值线段树可以过普通平衡树那道题,那么对于可持久化普通平衡树,我们是否也可以用主席树来搞一搞呢.答案是肯定的.只需要动态开点就行了.其他的跟普通平衡树那道题一模一样. 代码 这里需要注意一点,当 l 和 r 都是负数的时候, /2 就会有问题,因为 $ -5/2 = -2$ 而 $ -5 >> 1 = -3$ ,所以除2会使 l 一直小于mid,从而陷入死循环. #include <bits/stdc++.h> #define

C++ STL rope 可持久化平衡树 (可持久化数组)

官方文档好像 GG 了. rope 不属于标准 STL,属于扩展 STL,来自 pb_ds 库 (Policy-Based Data Structures). 基本操作: #include <ext/rope> // 头文件 using namespace __gnu_cxx; // 注意名称空间 rope<int> rp; int main() { rp.push_back(x); // 在末尾插入 x rp.insert(pos, x); // 在 pos 处插入 x rp.e

[您有新的未分配科技点]可,可,可持久化!?------可持久化线段树普及版讲解

最近跑来打数据结构,于是我决定搞一发可持久化,然后发现--一发不可收啊-- 对于可持久化数据结构,其最大的特征是"历史版本查询",即可以回到某一次修改之前的状态,并继续操作:而这种"历史版本查询"会衍生出其他一些强大的操作. 今天,我们主要讲解可持久化线段树.其实,它的另外一个名字"主席树"似乎更加为人所知(主席%%%). 主席树与普通的线段树相比,多出来的操作是在修改时复制修改的一条链,这个操作的过程大概长下面这样. 至于为什么要这样做-- 对