2017.6.28 文艺平衡树 思考记录

来源:互联网 发布:windows photo viewer 编辑:程序博客网 时间:2024/06/04 19:47

         再也不写指针splay了!!   又长又难调,有时还比数组慢、

         就学了hzwer的写法,融合了自己的习惯、、

               第一次写带标记的splay、、

               旋转的时候注意灵活运用splay功能

             区间操作打标记就是要旋转出独立区间,所以就需要两个端点的旋转,,

             要旋转的是l-1和r+1、

             由于l-1、r+1可能出界,所以如果要从1开始开,就需要整体+1,输出答案时整体-1

             新建的1和n+2是不可能被打标记、交换的,所以不用考虑交换混乱‘

             对于数组splay,交换只需一个swap、、

            

            还有操作时一定要常splay,,不然遇到链直接跪

            简单说明一下双旋的splay为何是log的

             因为遇到任何情况,它都能将自己走过的节点由链变成满一点的树

            而树的形态只能被splay改变,splay每次都将长的变成短的,,所以均摊下来每个点都会被变成满一点的树,,所以对于满的树查找就是log了

            所以无论干什么splay一次总是优秀的,要多splay(一次splay复杂度均摊最复杂为logn)


           码:

#include<iostream>#include<cstdio>#include<algorithm>using namespace std;#define N 400005int ch[N][2],fu[N],zhi[N],sz[N],rt,x,y,n,m,i,zy;bool rev[N];void up(int o){sz[o]=sz[ch[o][0]]+sz[ch[o][1]]+1;}void down(int o){if(rev[o]){swap(ch[o][0],ch[o][1]);rev[ch[o][0]]^=1;rev[ch[o][1]]^=1;rev[o]=0;}}int getwh(int o){return ch[fu[o]][0]==o?0:1;}void set(int o,int wh,int child)//只有fz,没有yy {ch[o][wh]=child;if(child!=0)fu[child]=o;up(o);}void rotate(int o){   down(o);int fa=fu[o];int ye=fu[fu[o]];int wh=getwh(o);set(fa,wh,ch[o][wh^1]);set(o,wh^1,fa);fu[o]=ye;if(ye!=0)ch[ye][ch[ye][0]==fa?0:1]=o;}void splay(int o,int tar){for(;fu[o]!=tar;rotate(o))if(fu[fu[o]]!=tar)getwh[o]==getwh[fu[o]]?rotate(fu[o]):rotate(o);if(tar==0)rt=o;}int find(int o,int wz){down(o);if(sz[ch[o][0]]+1==wz)return o;if(sz[ch[o][0]]+1<wz){if(ch[o][1]==0){zy=1;return o;}find(ch[o][1],wz-1-sz[ch[o][0]]);     }else {if(ch[o][0]==0){zy=0;return o;}find(ch[o][0],wz);    }}void gai(int l,int r){ int ll=find(rt,l); int rr=find(rt,r+2); splay(ll,0); splay(rr,rt); rev[ch[rr][0]]^=1;}int tot=0;int xin(int v){int now=++tot;zhi[now]=v;sz[now]=1;return now;}void ins(int wz,int v){   int newone=xin(v);  if(rt==0)  {rt=newone;return;}  int last=find(rt,wz); set(last,zy,newone);  splay(newone,0);}int main(){scanf("%d%d",&n,&m);for(i=1;i<=n+2;i++){ins(i,i);}for(i=1;i<=m;i++){scanf("%d%d",&x,&y);gai(x,y);}for(i=2;i<=n+1;i++){printf("%d ",find(rt,i)-1);}}


原创粉丝点击