小练习,splay区间反转

来源:互联网 发布:电路设计用什么软件 编辑:程序博客网 时间:2024/06/15 15:17

一道codevs的区间翻转问题。

http://codevs.cn/problem/1743/

题意,每次找最左边的数,令为k:   k=1,结束;  否则,ans++,翻转[1,k].

(给定的是全排列,所以,加两个点就可以直接做了。)


题目中说可能无解,但我觉得应该有解,所以就没管-1.   求大神指导一下到底是否一定有解。

(当然最好定义一个较大的操作数,大于此操作数仍无法结束程序,输出-1)


以下简要分析:

①两个虚拟点是极有用的,有了这两个虚拟点就避免讨论l=1时l-1找不到的情况。

②(我用的指针)插入的时候,一直向最右边插就可以了(记得每次把插入的点旋到根)~~~PS:我傻逼了,splay如果旋完我直接return 了,忘记如果旋到根要变root的指向。

③指针的操作就是不容易直接记录每个点的位置(好像可以直接找)(管它的,我写复杂了~) 所以我还用了size存左子数个数,每次找排名第2的(有虚拟节点),把它的值找到,是1结束,否则翻转。

其实我这样看似多余,实则是有必要的----  你每次直接调用地址进行操作,它上面可能有lazy标记没有变化,那么你操作完就有可能偏离了正常的答案,因此就需要从上往下依次找,每层下放lazy.

④pushdown是在每次往下查询的时候都要用到的,只要需要从根往下找,每层pushdown以下,操作类似于线段树。


之后就是常规的splay就可以了。

#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>#define maxn 300000+20using namespace std;int n;int cnt=0;struct node{node *f;node *ch[2];int key;int lazy;int size;}S[maxn];node *root;void pushup(node *u){u->size=1;if(u->ch[0])u->size+=u->ch[0]->size;if(u->ch[1])u->size+=u->ch[1]->size;}void pushdown(node *u){if(u==NULL||!u->lazy)return ;if(u->ch[0])u->ch[0]->lazy^=1;if(u->ch[1])u->ch[1]->lazy^=1;node *y;y=u->ch[0];u->ch[0]=u->ch[1];u->ch[1]=y;u->lazy=0;}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];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);}if(p==NULL)root=u;pushup(u);}void insert(int key){if(root==NULL){root=&S[++cnt];root->lazy=0;root->key=key;root->size=1;root->ch[0]=root->ch[1]=root->f=NULL;return ;}node *u=root;node *y;while(1){u->size++;/*if(key<u->key){if(u->ch[0])u=u->ch[0];else{y=&S[++cnt];y->lazy=0;y->ch[0]=y->ch[1]=NULL;y->size=1;y->key=key;y->f=u;u->ch[0]=y;break;}}else{*/if(u->ch[1])u=u->ch[1];else{y=&S[++cnt];y->lazy=0;y->ch[0]=y->ch[1]=NULL;y->key=key;y->size=1;y->f=u;u->ch[1]=y;break;}}splay(y,NULL);}node * find(int k){node *u=root;while(1){pushdown(u);int size=1;if(u->ch[0])size+=u->ch[0]->size;if(size==k)return u;if(k<size)u=u->ch[0];else {k-=size;u=u->ch[1];}}}int find2(){return find(2)->key;}void flip(int l,int r){//l,r+2node *ll=find(l);node *rr=find(r+2);splay(ll,NULL);splay(rr,root);root->ch[1]->ch[0]->lazy^=1;}void dfs(node *u){if(u->ch[0])dfs(u->ch[0]);printf("%d ",u->key);if(u->ch[1])dfs(u->ch[1]);}int main(){scanf("%d",&n);root=NULL;int x;insert(0);for(int i=1;i<=n;i++){scanf("%d",&x);insert(x);}insert(n+1);int ans=0;while(1){int k=find2();if(k==1)break;ans++;flip(1,k);}printf("%d\n",ans);return 0;}



1 0
原创粉丝点击