一直没有点动态树这个科技树,因为听说只能用Splay,用Treap的话多一个log。有一天脑洞大开,想到也许Treap也能从底向上Split。仔细思考了一下,发现翻转标记不好写,再仔细思考了一下,发现还是可以写的,只需要实时交换答案二元组里的两棵树,最后在吧提出来的访问节点放回去就行了。本着只学一种平衡树的想法,脑洞大开加偏执人格的开始写可持久化Treap版的Link Cut Tree。。。

  写了才发现,常数硕大啊!!!代码超长啊!!!因为merge是从上到下,split从下到上,pushdown要写两个啊!!Link Cut Tree巧妙运用Splay特性将最左和最右提取之后合并是O(1)的呀!!Treap还要merge一次常数++啊。我冤枉啊!我只是不想学Splay啊!!好吧,我还是把它写出来了。。。

题目:洞穴探测

代码:

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm> using namespace std;
int father[];
struct node
{
int num;
int key;
int left;
int right;
node* ls;
node* rs;
bool turn;
node* f;
node()
{
key=rand();
f=NULL;
}
}no[]; int root; void swap(node** a,node** b)
{
node* c=*a;
*a=*b;
*b=c;
} void swap(int* a,int *b)
{
int c=*a;
*a=*b;
*b=c;
} void pushdown(node* now)
{
if (now->turn)
{
swap(&now->ls,&now->rs);
if (now->ls)
{
now->ls->turn=!now->ls->turn;
swap(&now->ls->left,&now->ls->right);
}
if (now->rs)
{
now->rs->turn=!now->rs->turn;
swap(&now->rs->left,&now->rs->right);
}
}
now->turn=false;
} void update(node* now)
{
now->left=now->right=now->num;
if (now->ls)
now->left=now->ls->left;
if (now->rs)
now->right=now->rs->right;
} node* merge(node* a,node* b)
{
if (!a) {update(b);return b;}
if (!b) {update(a);return a;}
pushdown(a);
pushdown(b);
if (a->key<b->key)
{
a->rs=merge(a->rs,b);
a->rs->f=a;
update(a);
return a;
}
else
{
b->ls=merge(a,b->ls);
b->ls->f=b;
update(b);
return b;
}
} struct nodepair
{
node* l;
node* r; nodepair(node* a,node* b)
{
l=a;
r=b;
}
}; nodepair pushdown(node* now,bool lr,nodepair ret)
{
now->turn=false;
if (lr&&now->ls)
{
now->ls->turn=!now->ls->turn;
swap(&now->ls->left,&now->ls->right);
}
if (!lr&&now->rs)
{
now->rs->turn=!now->rs->turn;
swap(&now->rs->left,&now->rs->right);
}
swap(&now->ls,&now->rs);
swap(&ret.l,&ret.r);
if (ret.l)
{
ret.l->turn=!ret.l->turn;
swap(&ret.l->left,&ret.l->right);
}
if (ret.r)
{
ret.r->turn=!ret.r->turn;
swap(&ret.r->left,&ret.r->right);
}
return ret;
}
nodepair split(node* start)
{
pushdown(start);
node* cen=start;
nodepair ret(start->ls,start->rs);
if (start->ls)
start->ls->f=NULL;
if (start->rs)
start->rs->f=NULL;
start->ls=start->rs=NULL;
bool lr;
if (start->f)
if (start->f->ls == start)
lr=false;
else
lr=true;
node* now=start->f;
start->f=NULL;
while (now)
{
if (now->turn)
{
ret=pushdown(now,lr,ret);
lr=!lr;
}
node* next=now->f;
now->f=NULL;
if (lr)
{
now->rs=ret.l;
if (ret.l)
ret.l->f=now;
update(now);
ret.l=now;
}
else
{
now->ls=ret.r;
if (ret.r)
ret.r->f=now;
update(now);
ret.r=now;
}
if (next)
{
if (next->ls==now)
lr=false;
else
lr=true;
}
now=next;
}
ret.l=merge(ret.l,cen);
return ret;
} node* access(int num)
{
int now=num;
node* lasttree=NULL;
while (now!=)
{
nodepair km=split(&no[now]);
if (lasttree)
father[lasttree->left]=;
lasttree = merge(km.l,lasttree);
if (km.r)
father[km.r->left]=now;
now=father[lasttree->left];
}
return lasttree;
} bool query(int x,int y)
{
int k1=access(x)->left;
int k2=access(y)->left;
return k1==k2;
} void changeroot(int n)
{
node* road=access(n);
road->turn=!road->turn;
swap(&road->left,&road->right);
} void Connect(int x,int y)
{
changeroot(y);
access(x);
father[y]=x;
} void destroy(int x,int y)
{
changeroot(x);
access(x);
father[y]=;
} int main()
{
freopen("1839.in","r",stdin);
freopen("1839.out","w",stdout);
int n;
cin>>n;
for (int i=;i<=n;++i)
{
no[i].num=i;
father[i]=;
}
int q;
char cmd[];
scanf("%d",&q);
for (int i=;i<=q;++i)
{
int j,k;
scanf("%s%d%d",cmd,&j,&k);
if (cmd[]=='C')
{
Connect(j,k);
}
if (cmd[]=='Q')
{
if (query(j,k))
printf("Yes\n");
else
printf("No\n");
}
if (cmd[]=='D')
{
destroy(j,k);
}
}
return ;
}

2255ms 3769B

一坨翔啊!!!!不过麻麻再也不用担心我写不来动态树了。。。

准备过几天研究一下其他形式的可持久化TreapLCT,试着换种写法把常数降下来,代码量降下来。大概思想是先找到根,记录路径是走的左子树还是右子树,在走下来,感觉要好写很多。。。

现在觉得Splay和Treap各有各的优点,Treap好理解,一般较快。Splay特性很神奇,可以干一些奇奇怪怪的事情。。。

建议在我把常数降下来之前各位童鞋还是好好写Splay的LCT吧。。。

脑洞大开加偏执人格——可持久化treap版的Link Cut Tree的更多相关文章

  1. 脑洞大开加偏执人格——可持久化treap版的Link Cut Tree2

    试了一下先上再下的Treap方式,很高兴,代码变短了,但是,跑的变慢了!!!其实慢得不多,5%左右.而且这个版本的写法不容易写错..只要会一般可持久化Treap的人写着都不难...就是相对于(压行的) ...

  2. 指针版P3690 【模板】Link Cut Tree (动态树)

    题面 传送门 题解 鉴于数组版实在是太慢我用指针版重新写了一遍 代码基本是借鉴了lxl某道关于\(LCT\)的题 //minamoto #include<bits/stdc++.h> #d ...

  3. 平衡树与可持久化treap

    平衡树(二叉树) 线段树不支持插入or删除一个数于是平衡树产生了 常见平衡树:treap(比sbt慢,好写吧),SBT(快,比较好写,有些功能不支持),splay(特别慢,复杂度当做根号n来用,功能强 ...

  4. UVALive 6145 Version Controlled IDE(可持久化treap、rope)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  5. BZOJ 3595: [Scoi2014]方伯伯的Oj SBT+可持久化Treap

    3595: [Scoi2014]方伯伯的Oj Time Limit: 6 Sec  Memory Limit: 256 MBSubmit: 102  Solved: 54[Submit][Status ...

  6. 【模板】可持久化文艺平衡树-可持久化treap

    题目链接 题意 对于各个以往的历史版本实现以下操作: 在第 p 个数后插入数 x . 删除第 p 个数. 翻转区间 [l,r],例如原序列是 \(\{5,4,3,2,1\}\),翻转区间 [2,4] ...

  7. 高rong效chang的可持久化treap

    很多人觉得可持久化treap很慢,但是事实上只是他们可持久化treap的写法不对.他们一般是用split和merge实现所有功能,但是这样会有许多不必要的分裂.其实我们可以用一种特殊的方式来实现插入和 ...

  8. 可持久化Treap

    终于写了一次可持久化Treap,做的是可持久化序列的模板题. Treap Treap=Tree+Heap,是一个随机化的数据结构.它的每个节点至少有两个关键字,一个是我们要存储的\(val\),一个是 ...

  9. Codeforces - 38G 可持久化Treap 区间操作

    题意:\(n\)个人排队,每个人有重要度\(p\)和不要脸度\(c\),如果第\(i\)个人的重要度大于第\(i-1\)个人的重要度,那么他们之间可以交换,不要脸度-1,交换后先前的第\(i\)个人也 ...

随机推荐

  1. 2.Linux的用户、用户组、权限、文件系统管理及其网络配置

    2.1 Linux的用户及用户组 2.1.1 Linux的用户管理 用户账号管理包含以下三个方面: 用户账号的添加.删除.与修改 用户口令(密码)的管理 用户组的添加.删除管理 Linux系统中用户信 ...

  2. 洛谷——P1063 能量项链

    P1063 能量项链 题目描述 在MarsMars星球上,每个MarsMars人都随身佩带着一串能量项链.在项链上有NN颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对 ...

  3. hdu 5176 The Experience of Love

    The Experience of Love  Accepts: 11  Submissions: 108  Time Limit: 4000/2000 MS (Java/Others)  Memor ...

  4. Java基础学习总结(24)——Java单元测试之JUnit4详解

    Java单元测试之JUnit4详解 与JUnit3不同,JUnit4通过注解的方式来识别测试方法.目前支持的主要注解有: @BeforeClass 全局只会执行一次,而且是第一个运行 @Before  ...

  5. Leetcode 30.与所有单词相关联的子串

    与所有单词相关联的字串 给定一个字符串 s 和一些长度相同的单词 words.在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置. 注意子串要与 words 中的单词完全匹配,中间不能 ...

  6. [TS-A1489][2013中国国家集训队第二次作业]抽奖[概率dp]

    概率dp第一题,开始根本没搞懂,后来看了09年汤可因论文才基本搞懂,关键就是递推的时候做差比较一下,考虑新加入的情况对期望值的贡献,然后推推公式(好像还是不太会推qaq...) #include &l ...

  7. mongodb之监控

    监控方式 命令行工具 mongostat命令 用途 用于mongod或者mongos操作类型统计,网络流量统计,当前并发数等统计 用法 mongostat options <sleeptime& ...

  8. javac compiling error ( mising package)

    javac 编译java源文件时,提示 package does not exist 的错误 Test.java import java.security.MessageDigest; import ...

  9. jQuery和CSS3炫酷button点击波特效

    这是一款效果很炫酷的jQuery和CSS3炫酷button点击波特效.该特效当用户在菜单button上点击的时候.从鼠标点击的点開始,会有一道光波以改点为原点向外辐射的动画效果,很绚丽. 在线演示:h ...

  10. 4.非关系型数据库(Nosql)之mongodb:普通索引,唯一索引

     一:普通索引 1创建一个新的数据库 > use toto; switched to db toto > show dbs; admin (empty) local 0.078GB & ...