替罪羊树求助
查看原帖
替罪羊树求助
298051
xkcdjerry楼主2020/8/1 16:21

刚开始2AC+2WA+8RE (五彩缤纷) ,后来特判没有存在的情况达到4AC+8RE,即使取消abort也不行,本地死活调不出来。
求大佬帮我指一下方向,这些点RE是有什么可能的原因orz。
谢谢! (评测链接
代码:

#include <cstdlib>
#include <vector>
#include <cstring>
using std::vector;
typedef int T;
//more bst options than sgt.cpp!
struct node
{
	node *l,*r,*fa;
	int size,del_cnt;
	bool del;
	T val;
};
struct sgt
{
	//so if the tree is empty, we can set sgt.head to NULL
	//and not need a pass-by-ref or double pointer
	//I HATE those things
	node *head;
};
#define _SELECT(no,v) v<no->val ? no->l : no->r
#define SELECT(no,v) (_SELECT((no),(v)))
namespace internal
{
	//internal functions
	node *alloc()
	{
		//alloc with null pointer check and defaults
		node *t=(node*)malloc(sizeof(node));
		if(!t)
		{
			puts("Bad alloc!");
			abort();
		}
		t->fa=t->l=t->r=NULL;
		t->del=false;
		t->size=1;
		t->del_cnt=0;
		return t;
	}
	//rebuild functions
	
	void splat(node *t,vector<T> &v)
	{
		if(!t) return;
		splat(t->l,v);
		if(!t->del) v.push_back(t->val);
		splat(t->r,v);
	}
	node *build(vector<T> &v,int l,int r)
	{
		if(l==r) return NULL;
		node *t=alloc(),*tmp;
		t->size=r-l;
		int mid=(r+l)/2;
		t->val=v[mid];
		tmp=build(v,l,mid);
		if(tmp) tmp->fa=t;
		t->l=tmp;
		tmp=build(v,mid+1,r);
		if(tmp) tmp->fa=t;
		t->r=tmp;
		return t;
	}
	void destroy(node *t)
	{
		if(!t) return;
		destroy(t->l);
		destroy(t->r);
	}
	node* rebuild(node *t)
	{
		int size=t->size;
		vector<T> v;
		splat(t,v);
		node *new_node=build(v,0,size);
		destroy(t);
		if(new_node)
			return new_node;
		else
		{
			puts("Rebuild on an empty tree!");
			abort();
		}
		
	}
	inline int get_size(node *t)
	{
		return t?t->size:0;
	}
	inline bool needs_rebuild(node *t)
	{
		const float a=0.75;
		return get_size(t->l) > t->size*a ||
		       get_size(t->r) > t->size*a ||
		       t->del_cnt > t->size*a;
	}
	void dup(node *a,node *b)
	{
		SELECT(a->fa,a->val)=b;
		b->fa=a->fa;
	}
	void test_rebuild(sgt *t,node *n)
	{
		//work up from t to ROOT and find the biggest tree that needs rebuilding
		//then rebuild it
		node *violater=NULL;
		while(n)
		{
			if(needs_rebuild(n)) violater=n;
			n=n->fa;
		}
		if(violater)
		{
			if(violater==t->head)
				t->head=rebuild(violater);
			else
				dup(violater,rebuild(violater));
			free(violater);
		}
	}
}
using internal::destroy; //暴露一定的接口QAQ 


//BST operations
void insert(sgt *t,T val) 
{
	if(t->head)
	{
		node *no=t->head;
		node *last=NULL;
		while(no)
		{
			no->size++;
			last=no;
			no=SELECT(no,val);
		}
		node *new_node=internal::alloc();
		new_node->val=val;
		new_node->fa=last;
		SELECT(last,val)=new_node;
		internal::test_rebuild(t,new_node);
	}
	else
	{
		node *new_node=internal::alloc();
		new_node->val=val;
		t->head=new_node;
	}
}

node *search(sgt *t,T val)
{
	node *no=t->head;
	while(no)
	{
		if(no->val==val&&!no->del) return no;
		no=SELECT(no,val);
	}
	return NULL;
}

bool exists(sgt *t,T val)
{
	return search(t,val)!=NULL;
}

bool remove(sgt *t,T val)
{
	//if val exists in t
	//remove one existance of val and return true
	//else,do nothing and return false
	node *no=search(t,val);
	if(no)
	{
		node *tmp=no;
		//normal deletion
		no->del=true;
		while(tmp)
		{
			tmp->size--;
			tmp->del_cnt++;
			tmp=tmp->fa;
		}
		if(t->head->size==0)
		{
			//free the whole tree
			destroy(t->head);
			t->head=NULL;
		}
		else if(no->size==0)
		{
			internal::dup(no,NULL);
			destroy(no);
		}
		else
		{
			internal::test_rebuild(t,no);
		}
		return true;
	}
	else
	{
		return false;
	}
}

int _lesser_cnt(node *n,T val)
{
	//return the number of values smaller than val
	//in a tree with a root of n
	//note this is one smaller than rank(n,val)
	if(!n) return 0;
	if(val < n->val)
	{
		/*
		if val < n->val, then val will be smaller than ALL of the values in n->r
		so the values smaller than val will all be in n->l
		so _lesser(n,val)=_lesser(n->l,val)
		*/
		return _lesser_cnt(n->l,val);
	}
	else if(val==n->val)
	{
		/*
		if val==n->val, then val will be bigger than ALL of the values in n->l
		but <= all values in n->r
		so _lesser(n,val)=size(n->l)
		*/
		return internal::get_size(n->l);
	}
	else
	{
		/*
		if val>n->val, then val will be bigger than ALL of the values in n->l and the root
		but there is no clear promise of the relationship between it and the values in n->r
		so
		_lesser(n,val)=size(n->l)+
		               _lesser(n->r,val)+
		               1 (the ROOT)
		(but if the root is deleted, you MUST NOT add the 1)
		*/
		return internal::get_size(n->l)+_lesser_cnt(n->r,val)+(n->del?0:1);
	}
}

inline int rank(sgt *h,T val)
{
	return _lesser_cnt(h->head,val)+1;
}

node* _k_smaller_nodes(node *n,int k)
{
	/*
	return the node with k nodes smaller than it in a tree with root node n
	note that this is not equal to the kth rank
	this is instead equal to the k-1 th rank
	*/
	int lsize=internal::get_size(n->l);
	if(k<lsize)
	{
		//if k is smaller than the size of the left tree
		//then the node WILL fall in n->l
		return _k_smaller_nodes(n->l,k);
	}
	else if(k==lsize&&!n->del)
	{
		//the node is larger than the whole left tree
		//and the root is not deleted
		//then the required node is the root "n"
		return n;
	}
	else
	{
		//if it does not land in the left tree or the root
		//then it must be in the right subtree
		//note: it is already bigger than the whole left tree and (maybe) the root.
		//so it should be _k_smaller_node(n->r,k-size(n->l)-(n->del?0:1))
		return  _k_smaller_nodes(n->r,k-lsize-(n->del?0:1));//
	}
}

inline T kth(sgt *h,int k)
{
	//return the node ranked k
	return _k_smaller_nodes(h->head,k-1)->val;
}

T predecessor(sgt *h,T val)
{
	//return the first element before val
	int r=rank(h,val);
	if(r>1)
		return kth(h,r-1);
	else
	{
		puts("predecessor called on first element!");
		abort();
	}
}
T successor(sgt *h,T val)
{
	//return the first element after val
	int r=rank(h,val);
	if(exists(h,val)&&r < h->head->size)
		return kth(h,r+1);
	else if(!exists(h,val)&&r <= h->head->size)
	    return kth(h,r);
	else
	{
		puts("successor called on last element!");
		abort();
	}
}

int main()
{
	sgt h;
	h.head=NULL;
	
	int n;
	scanf("%d",&n);
	while(n--)
	{
		int opt,x;
		scanf("%d%d",&opt,&x);
		switch(opt)
		{
			case 1:insert(&h,x);break;
			case 2:remove(&h,x);break;
			case 3:printf("%d\n",rank(&h,x));break;
			case 4:printf("%d\n",kth(&h,x));break;
			case 5:printf("%d\n",predecessor(&h,x));break;
			case 6:printf("%d\n",successor(&h,x));break;
		}
	}
	return 0;
}
2020/8/1 16:21
加载中...