HDU3487 Play with Chain (Splay)

来源:互联网 发布:java编程99乘法表 编辑:程序博客网 时间:2024/05/16 01:02

题意:给两种操作,一种是切下[a,b]这一段加到c这个位置之后,还有一个翻转[a,b]这个位置,操作过后输出序列。

Splay。。。。虽然理论比较简单,但本渣还是写了一下午+调了3个小时。。。

对于两种操作,切下来的时候就是先把a-1旋转到根,然后把b+1旋转到a-1那个节点的右边,然后b+1这个节点的左子树就是[a,b]的序列了,插入把c旋转到根,c+1旋转到根的右边,然后直接插入到c+1的左子树就好了(这时一定是空的)。。翻转就好像线段树那样,弄个延迟标记就好了。

有很多细节要想清。。。首先,pushup和pushdown的位置要考虑清楚,然后就是注意边界的问题,比如1为左边界,那么我们就是查0这个点了,如果建树只建了1-n就会RE(我RE了几次),所以这里要想清,最后,我居然最后把dfs输出给写错了,导致样例都没过。。。还是太弱了。。。

#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;const int MAXN=300010;vector<int> ans;int num[MAXN];struct Node{Node *ch[2];Node *fa;int val,mark;int size;}p[MAXN];Node *null=&p[0];int tot=0;Node *root=null;//debug部分copy from hh void Treaval(Node *x) {        if(x!=null) {            Treaval(x->ch[0]);            printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,key = %2d   mark=%d\n",x->val,x->ch[0]->val,x->ch[1]->val,x->fa->val,x->size,x->val,x->mark);            Treaval(x->ch[1]);        }    }    void debug() {printf("%d\n",root->val);Treaval(root);}    //以上Debug  void pushup(Node *rt){rt->size=1;if(rt->ch[0]!=null)rt->size+=rt->ch[0]->size;if(rt->ch[1]!=null)rt->size+=rt->ch[1]->size;}void pushdown(Node *rt){if(rt->mark){rt->ch[0]->mark^=1;rt->ch[1]->mark^=1;rt->mark=0;swap(rt->ch[0],rt->ch[1]);}}void Rotate(Node *x,int c){Node *y=x->fa;pushdown(y);pushdown(x);y->ch[!c]=x->ch[c];if(x->ch[c]!=null)x->ch[c]->fa=y;x->fa=y->fa;if(y->fa!=null){if(y->fa->ch[0]==y)y->fa->ch[0]=x;elsey->fa->ch[1]=x;}x->ch[c]=y;y->fa=x;if(y==root)x=root;pushup(y);}void splay(Node *x,Node *f){if(x==null)return;while(x->fa!=f){if(x->fa->fa==f){if(x->fa->ch[0]==x)Rotate(x,1);elseRotate(x,0);}else{Node *y=x->fa,*z=y->fa;if(z->ch[0]==y){if(y->ch[0]==x)Rotate(y,1),Rotate(x,1);elseRotate(x,0),Rotate(x,1);}else{if(y->ch[1]==x)Rotate(y,0),Rotate(x,0);elseRotate(x,1),Rotate(x,0);}}pushup(x);}}Node *new_Node(int val){Node *rt=&p[++tot];rt->ch[0]=rt->ch[1]=rt->fa=null;rt->size=1;rt->mark=0;rt->val=val;return rt;}Node *build(int l,int r){if(l>r)return null;int mid=(l+r)>>1;Node *rt=new_Node(num[mid]);rt->ch[0]=build(l,mid-1);rt->ch[1]=build(mid+1,r);rt->ch[0]->fa=rt->ch[1]->fa=rt;pushup(rt);return rt;}Node *kth(Node *rt,int k){pushdown(rt);if(rt->ch[0]->size+1==k)return rt;else if(rt->ch[0]->size>=k)return kth(rt->ch[0],k);elsereturn kth(rt->ch[1],k-rt->ch[0]->size-1);}void solvecut(int a,int b,int c){Node *L,*R;L=kth(root,a);splay(L,null);R=kth(L,b+2);splay(R,L);Node *root1=R->ch[0];root1->ch[0]->fa=null;R->ch[0]->fa=null;R->ch[0]=null;Node *LL=kth(L,c+1);Node *RR=kth(L,c+2);splay(LL,null);splay(RR,LL);RR->ch[0]=root1;root1->fa=RR;splay(root1,null);splay(root,null);}void solveflip(int a,int b){Node *L,*R;L=kth(root,a);splay(L,null);root=L;R=kth(root,b+2);splay(R,L);R->ch[0]->mark^=1;}int flag;void prin(Node *rt){if(rt==null)return;pushdown(rt);prin(rt->ch[0]);ans.push_back(rt->val);prin(rt->ch[1]);//printf("size=%d val=%d\n",rt->size,rt->val);}int main(){int n,m,i,a,b,c;while(scanf("%d%d",&n,&m)==2){if(n==-1&&m==-1)break;char op[10];if(n==1){scanf("%s",op);if(op[0]=='C')scanf("%*d%*d%*d");elsescanf("%*d%*d");printf("1\n");}//null->fa=null->ch[0]=null->ch[1]=null;ans.clear();tot=0;for(i=0;i<=n+2;i++)num[i]=i;num[n+1]=num[n+2]=0;root=build(0,n+2);//debug();while(m--){scanf("%s",op);if(op[0]=='C'){scanf("%d%d%d",&a,&b,&c);solvecut(a,b,c);//debug();}else{scanf("%d%d",&a,&b);solveflip(a,b);}}flag=1;prin(root);//debug();for(i=0;i<ans.size();i++){if(ans[i]==0)continue;if(flag)printf("%d",ans[i]);elseprintf(" %d",ans[i]);flag=0;}printf("\n");}return 0;}


0 0
原创粉丝点击