刚开始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;
}