splay区间翻转及删除区间,平移区间

来源:互联网 发布:织梦cms模板下载 编辑:程序博客网 时间:2024/05/29 14:58

研究了很长时间,花费了一个下午debug,终于调出来了

hdu 3487 play with chain

http://acm.hdu.edu.cn/showproblem.php?pid=3487


两个操作(指针实现)


cut l,r, c把[l,r]剪下来放到剩下序列中第c个后面的位置.

flip l r 把[l,r]翻转(lazy标记,每次交换左右节点)


cut思路:把l-1旋到根,r+1旋到根的右节点,取下这一段;在剩下的序列中找到c,c+1的位置,把c旋到根,c+1旋到右节点,插入。

由平衡树性质易证得是对的(中序遍历恒定)


flip思路:把l-1旋到根,r+1旋到右节点,打上lazy标记。


最后访问的时候需要pushdown.

(中间每次splay,rotate都需要pushdown)


AC代码(调了好久,蒟蒻一枚)

#include<cstdio>#include<queue>#include<iostream>#include<algorithm>#include<cmath>#include<cstring>#include<cstdlib>#define maxn 330000+20using namespace std;int n,q;int cnt=0;struct node{node *f;node *ch[2];int size;int lazy;int id;}S[maxn];node *root;void pushdown(node *u){if((!u->lazy)||(u==NULL))return ;if(u->ch[0]!=NULL)u->ch[0]->lazy^=1;if(u->ch[1]!=NULL)u->ch[1]->lazy^=1;node *y=u->ch[0];u->ch[0]=u->ch[1];u->ch[1]=y;u->lazy=0; }void pushup(node *u){u->size=1;if(u->ch[0]!=NULL)u->size+=u->ch[0]->size;if(u->ch[1]!=NULL)u->size+=u->ch[1]->size;}void rotate(node *u){node *f=u->f;if(f==NULL)return ;pushdown(u);pushdown(f);node *ff=f->f;int d=u==f->ch[1];int dd=0;if(ff!=NULL)dd=f==ff->ch[1];if(u->ch[d^1])u->ch[d^1]->f=f;f->ch[d]=u->ch[d^1];/*int size=u->size;u->size=f->size;f->size=f->size-size;if(u->ch[d^1]!=NULL)f->size+=u->ch[d^1]->size;*/f->f=u;u->ch[d^1]=f;if(ff!=NULL)ff->ch[dd]=u;u->f=ff;pushup(f);pushup(u);}void splay(node *u,node *p){pushdown(u);while(u->f!=p){node *f=u->f;node *ff=f->f;if(ff==p){rotate(u);break;}int d=u==f->ch[1];int dd=f==ff->ch[1];if(d==dd)rotate(f);else rotate(u);rotate(u);}pushup(u);if(p==NULL)root=u;}void insert(int id){if(root==NULL){node *y=&S[++cnt];y->id=id;y->size=1;y->ch[0]=NULL;y->ch[1]=NULL;y->f=NULL;y->lazy=0;root=y;return ;}node *u=root;node *y;while(1){u->size++;if(id<u->id){//左边if(u->ch[0]!=NULL)u=u->ch[0];else{y=&S[++cnt];        y->id=id;        y->size=1;        y->ch[0]=NULL;y->ch[1]=NULL;        y->f=u;        u->ch[0]=y;        y->lazy=0;        break;} }else{if(u->ch[1]!=NULL)u=u->ch[1];else{y=&S[++cnt];        y->id=id;        y->size=1;        y->ch[0]=NULL;y->ch[1]=NULL;        y->f=u;        u->ch[1]=y;        y->lazy=0;        break;}}}splay(y,NULL);}char s[10];node *find (int x){node *u=root;while(1){int xx=1;if(u->ch[0]!=NULL)xx+=u->ch[0]->size;if(xx==x)return u;if(x<xx)u=u->ch[0];else {x-=xx;u=u->ch[1];}}}void cut(int l,int r,int c){node *x=find(l);node *y=find(r+2);splay(x,NULL);splay(y,root);node *u=root->ch[1]->ch[0];/*root->size-=u->size;root->ch[1]->size-=u->size;*/root->ch[1]->ch[0]=NULL;pushup(root->ch[1]);pushup(root);//u->f=NULL;node *yy=find(c+1);splay(yy,NULL);node *xx=find(c+2);splay(xx,root);//插入 root->ch[1]->ch[0]=u;u->f=root->ch[1];//root->ch[1]->size+=u->size;//root->size+=u->size;pushup(root->ch[1]);pushup(root);}void flip(int l,int r){node *x=find(l);node *y=find(r+2);splay(x,NULL);splay(y,root);node *u=root->ch[1]->ch[0];u->lazy^=1; }void dfs(node *u){//printf("debug :  %d  %d\n",u->size,u->id);pushdown(u);if(u->ch[0])dfs(u->ch[0]);if(u->id!=0&&u->id!=n+1)printf("%d ",u->id);if(u->ch[1])dfs(u->ch[1]); }int main(){freopen("hoho.txt","r",stdin);while(scanf("%d%d",&n,&q)!=EOF&&!(n<0&&q<0)){cnt=0;root=NULL;for(int i=0;i<=n+1;i++)insert(i);for(int i=1;i<=q;i++){scanf("%s",s);if(s[0]=='C'){int a,b,c;scanf("%d%d%d",&a,&b,&c);cut(a,b,c);}else{int a,b;scanf("%d%d",&a,&b);flip(a,b);}}dfs(root);printf("\n");}return 0;}

注意控制格式。

1 0