4月8日 各种树的乱搞

保留几个还没有看完的网页

https://www.sogou.com/sogou?query=splay%E5%A5%97%E7%BA%BF%E6%AE%B5%E6%A0%91&ie=utf8&_ast=1491658880&_asf=null&w=01029901&pid=sogou-clse-60a70bb05b08d6cd&duppid=1&cid=&cid=&sut=3100&sst0=1491659185439&lkt=0%2C0%2C0&sugsuv=00E601EC791FCD1758E8C284B93A4997&sugtime=1491659185439


http://www.docin.com/p-270751935.html

http://blog.csdn.net/chunkitlau/article/details/51787319

http://www.sogou.com/tx?user_ip=121.31.205.23&sourceid=hint&bh=1&hintidx=1&query=splay%E6%A0%91&hdq=sogou-site-706608cfdbcc1886-0001&duppid=1&cid=qb7.zhuye&w=01020600&interation=&interV=kKIOkrELjb8TkKIMkLELjbkRmLkElbYTkKIKmbELjboJmLkEk78TkKILkY==_-1167014467&htdbg=idc%3Egdylj%7CdbgID%3E01%7Cabt%3E7%7Cmth%3E1&ie=utf8&ref=360

http://www.sogou.com/sogou?query=%E4%BB%80%E4%B9%88%E5%8F%AB%E6%A0%91%E5%A5%97%E6%A0%91&pid=sogou-clse-60a70bb05b08d6cd

http://www.sogou.com/tx?query=%E7%BA%BF%E6%AE%B5%E6%A0%91%E5%A5%97%E5%B9%B3%E8%A1%A1%E6%A0%91&ie=utf8&_ast=1491659264&_asf=null&w=01029901&hdq=sogou-clse-a495eebbfa243b79-0001&duppid=1&cid=&sut=5029&sst0=1491659383886&lkt=0%2C0%2C0&sugsuv=00E601EC791FCD1758E8C284B93A4997&sugtime=1491659383886

http://blog.csdn.net/Sunshine_cfbsl/article/details/52184562?locationNum=1&fps=1

http://tieba.baidu.com/p/2152061053



#include<cstdio>
#define maxn 1000
int son[maxn][maxn],father[maxn],key[maxn],mi[maxn],mx[maxn],size[maxn];//son[x][0]=y表示节点x的左儿子是y;
int n,m,tip=0,num=0;
bool flag(int now)
{return son[father[now]][1]==now;}//左儿子返回零,右儿子返回一
void updata(int pos)
{size[pos]=size[son[pos][0]]+size[son[pos][1]]+1;}
void rotate(int now)//rotate now是指将now绕father rotate。有两个方向,表示now是father的左儿子还是右儿子。
{
    int fa=father[now],fx=flag(now);//儿子编号
    son[fa][fx]=son[now][!fx];
    if(son[now][!fx])
    father[son[now][!fx]]=fa;   //连接father和son[now][!fx]
    son[father[fa]][flag(fa)]=now;
    father[now]=father[fa];    //连接grandpa和now
    son[now][!fx]=fa;
    father[fa]=now;    //连接now和father
    updata(fa);updata(now);//rotate完成后要updata
}
void splay(int now,int root)//通过方向标记,将两个方向的rotate合成一个。
{
    while(father[now]!=root)
{
        if(father[father[now]]!=root)
            if(flag(now)==flag(father[now]))rotate(father[now]);
            else rotate(now);
        rotate(now);
    }
}
int kth(int now,int th)//寻找k小值的标号
{
    if(size[son[now][0]]+1==th)return now;
    else if(size[son[now][0]]+1>th)return kth(son[now][0],th);
    else return kth(son[now][1],th-size[son[now][0]]-1);
}
int pre(int val)//寻找前驱
{
    int tmp=kth(son[val][0],size[son[val][0]]);
    splay(tmp,val);
    return key[tmp];
}
int succ(int val)//寻找后继
{
int tmp=kth(son[val][1],1);
    splay(tmp,val);
    return key[tmp];
}
int getpos(int now,int val)//找到一个合适的位置插入
{
if((key[now]<val)&&(size[son[now][1]]))return getpos(son[now][1],val);
    else if((key[now]>val)&&(size[son[now][0]]))return getpos(son[now][0],val);
    return now;
}
void insert(int root,int pos,int val)//并不能保证这个点是大于还是小于插入节点
{
    int sroot=father[root];
    splay(root=getpos(root,val),sroot);
    if(key[root]<val)
{
        succ(root);//十分重要!!!!
        rotate(root=son[root][1]);
    }
    int tmp=son[root][0];key[pos]=val;
    son[root][0]=pos;father[pos]=root;
    son[pos][0]=tmp;father[tmp]=pos;
    updata(pos);updata(root);
    splay(pos,0);
}
//我们把刚好比插入点大的点作为根,在左子树插入。
//如果根小于插入点,则要将根的[后继]变成根(注意不是根的右儿子!!!)
//至此splay的基本操作我们都完成了。
//对于有重复元素的题,就得特殊处理一下。
//find的时候必须找最小序号的哪一个,pre和succ查询的数可能不在splay中,要做一点处理。
void dele(int root,int val)//删除
{
    int sroot=father[root];
    splay(root=find(root,val),sroot);
    if(son[root][1])splay(succ(root),root);
    son[sroot][flag(root)]=son[root][1];
    father[son[root][1]]=sroot;
    son[son[root][1]][0]=son[root][0];
    father[son[root][0]]=son[root][1];
    updata(son[root][1]);
}
int rank(int now,int val)//查找标号
{
    if(key[now]==val)return size[son[now][0]]+1;
    else if(val<key[now])return rank(son[now][0],val);
    else if(val>key[now])return size[son[now][0]]+1+rank(son[now][1],val);
}
int find(int now,int val)//另外一个查找
{//pos
    if(mx[son[now][0]]>=val)return find(son[now][0],val);
    if(key[now]==val)return now;
    if(mi[son[now][1]]<=val)return find(son[now][1],val);
    return now;
}



#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 10000
int n,root,son[maxn][2],fa[maxn],weight[maxn];
int askflag(int x)
{if(son[fa[x]][0]==x) return 0;return 1;}
void updata(int x)
{
while(1)
{
weight[x]=weight[son[x][0]]+weight[son[x][1]];
if(x==root) break;
x=fa[x];
}
}
void rorate(int now)
{
int flag1=askflag(now),f2=askflag(fa[now]),father=fa[now],grandpa=fa[fa[now]];
fa[now]=grandpa;
son[grandpa][f2]=now;
fa[son[now][(flag1+1)%2]]=father;
son[father][flag1]=son[now][(flag1+1)%2];
son[now][(flag1+1)%2]=father;
fa[father]=now;
updata(now);updata(father);
}
void splay(int now,int root)
{
while(now!=root)
{
if(fa[now]!=root)
 if(askflag(fa[now])!=flag(now))rorate(fa[now]);
 else rorate(now);
rorate(now);
}
}
int main()
{

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值