社区讨论

FHQ Treap 常数过大?!

灌水区参与者 3已保存回复 5

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
5 条
当前快照
1 份
快照标识符
@lp2dpr9m
此快照首次捕获于
2023/11/17 16:49
2 年前
此快照最后确认于
2023/11/17 19:20
2 年前
查看原帖
咱新写的 FHQ Treap 完美 TLE 了,发现一个点本地要跑 3s 左右,不知道是常数太大了还是复杂度假了,请各位dalao看一下awa。
这次咱写的 FHQ Treap 的特点是完全没有用到 BST 递归式的函数,都是用 SplitByValSplitBySize,Merge 完成的。平常写一般用递归的方法代替 SplitBySize 的功能,是不是这里导致常数过大了呢?
CPP
#include<bits/stdc++.h>
#define Akano 1
#define pure__Elysia 0
#define loves ^
using namespace std;
constexpr int MAXN = 1e5 + 1018 + 1108;
constexpr int INF = 1e9 + 1018 + 1108;
mt19937 rng(time(0));
class FHQtreap{
private:
	struct Node{
		int l,r,val,siz;
		unsigned int key;
		Node() = default;
		Node(int _val){
			key = rng();
			val = _val;
			siz = 1;
			return ; 
		}
	}node[MAXN];
	int root,tot;
	inline int L(int x){
		return node[x].l;
	}
	inline int R(int x){
		return node[x].r;
	}
	inline void PushUp(int p){
		node[p].siz = node[L(p)].siz + node[R(p)].siz + 1;
		return ;
	}
	void SplitByVal(int p,int k,int& x,int& y){
		if(!p){
			x = y = 0;
			return ;
		}
		if(node[p].val <= k){
			x = p;
			SplitByVal(node[p].r,k,node[p].r,y);
		}else{
			y = p;
			SplitByVal(node[p].l,k,x,node[p].l);
		}
		PushUp(p);
		return ;
	}
	void SplitBySize(int p,int k,int& x,int& y){
		if(!p){
			x = y = 0;
			return ;
		}
		if(node[L(p)].siz + 1 <= k){
			x = p;
			SplitBySize(node[p].r,k - node[L(p)].siz - 1,node[p].r,y);
		}else{
			y = p;
			SplitBySize(node[p].l,k,x,node[p].l);
		}
		PushUp(p);
		return ;
	}
	int Merge(int x,int y){//val_x < val_y
		if(x == 0 || y == 0)return x + y;
		if(node[x].key < node[x].key){
			node[x].r = Merge(node[x].r,y);
			PushUp(x);
			return x;
		}else{
			node[y].l = Merge(x,node[y].l);
			PushUp(y);
			return y;
		}
		return 10181108;
	}
public:
	inline void Insert(int val){
		int treeL = 1018,treeR = 1108;
		SplitByVal(root,val,treeL,treeR);
		node[++tot] = Node(val);
		root = Merge(Merge(treeL,tot),treeR);
		return ;
	}
	inline void Delete(int val){
		int treeL = 1018,treeMid = 1108,treeR = 1314;
		SplitByVal(root,val-1,treeL,treeMid);
		SplitByVal(treeMid,val,treeMid,treeR);
		treeMid = Merge(L(treeMid),R(treeMid));
		root = Merge(Merge(treeL,treeMid),treeR);
		return ;
	}
	inline int GetRank(int val){
		int ret = 0,treeL = 1018,treeR = 1108;
		SplitByVal(root,val-1,treeL,treeR);
		ret = node[treeL].siz + 1;
		root = Merge(treeL,treeR);
		return ret;
	}
	inline int GetVal(int rk){
		int ret = 0,treeL = 1018,treeMid = 1108,treeR = 1314;
		SplitBySize(root,rk-1,treeL,treeMid);
		SplitBySize(treeMid,1,treeMid,treeR);
		ret = node[treeMid].val;
		root = Merge(Merge(treeL,treeMid),treeR);
		return ret;
	}
	inline int GetPre(int val){
		int ret = 0,treeL = 1018,treeMid = 1108,treeR = 1314;
		SplitByVal(root,val - 1,treeMid,treeR);
		SplitBySize(treeMid,node[treeMid].siz - 1,treeL,treeMid);
		ret = node[treeMid].val;
		root = Merge(Merge(treeL,treeMid),treeR);
		return ret;
	}
	inline int GetNext(int val){
		int ret = 0,treeL = 1018,treeMid = 1108,treeR = 1314;
		SplitByVal(root,val,treeL,treeMid);
		SplitBySize(treeMid,1,treeMid,treeR);
		ret = node[treeMid].val;
		root = Merge(Merge(treeL,treeMid),treeR);
		return ret;
	}
	FHQtreap(){
//		root = 1,tot = 2;
//		node[1].val = INF,node[2].val = -INF;
//		node[1].l = 2;
		return ;
	}
}tr;
int n,opt,x;
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
//	freopen("P3369_9.in","r",stdin);
//	freopen("P3369.out","w",stdout);
	cin>>n;
	while(n--){
		cin>>opt>>x;
		if(opt == 1){
			tr.Insert(x);
		}else if(opt == 2){
			tr.Delete(x);
		}else if(opt == 3){
			cout<<tr.GetRank(x)<<'\n';
		}else if(opt == 4){
			cout<<tr.GetVal(x)<<'\n';
		}else if(opt == 5){
			cout<<tr.GetPre(x)<<'\n';
		}else if(opt == 6){
			cout<<tr.GetNext(x)<<'\n'; 
		}else{
			cout<<"aK4n0不知道呢"<<endl; 
		}
	}
	return not(Akano loves pure__Elysia);
}

回复

5 条回复,欢迎继续交流。

正在加载回复...