zoukankan      html  css  js  c++  java
  • LCT

    原理

    懒得讲了

    应用(你会发现这就是(fAKe_Hu)的题单)

    维护链信息

    luoguP1501

    维护链懒标记的裸题

    弹飞绵羊

    每个点向右边弹到的点连边,超过(n)的所有点连向(n+1),最后形成一棵树,一个点(splay)到根后左儿子的数量(深度)就是最后答案

    luoguP4332

    记录一个节点的权值为(0-3)表示接受的(1)状态的数量

    考虑每次更改一次节点状态,会自底部向上修改连续一段节点的状态

    我们可以平衡树上二分找第一个权值为(1/2)的节点,也可以直接数组记录,然后把它换到根

    注意修改完之后记录(1/2)的数组要交换,如果这个节点不存在就把整条链都修改

    动态维护连通性

    luoguP2147

    裸题,(link)(cut)操作

    luoguP2542

    常见套路是删边变倒序加边

    先将没有被删去的边连起来,我们把每条边中间加一个点,然后把新加的点且在原图中是割点的的点权都变成(1)

    倒序操作序列,加边的时候如果两个点不连通就直接连边,让新加的点边权为(1)

    否则把那个点到根的权值全部变为(0)

    查询操作就是两点间的权值

    bzoj2959

    (1)操作:连接两个跑道,如果已经联通,那么就把路径上所有点用并查集合并,把所有点的权值给根节点

    (2)操作:修改该节点根节点权值

    (3)操作:求链和

    没写,口胡的(

    动态维护生成树

    水管局长

    删边变逆序加边

    (link)一条边时,如果两点已经联通,那么二分找到边权最大的边(边化点),然后替换掉

    最小差值生成树

    将边权从小到大排序插入(LCT),形成生成树之后每次把边权最小的边换掉,计算答案

    膜法森林

    将边按一个关键字排序,维护另一个关键字的最小生成树

    维护子树

    大融合

    求一条边两个端点虚子树点数之和

    其实就两步,(link)的时候一个节点加上另一个节点总儿子数,(access)的时候加上原右子树减去新右子树

    QTREE5

    这是个神仙状态

    (dp1[x],dp2[x])分别表示在(splay)(x)子树里面深度最浅的点最近的白点的距离 和 深度最深的点最近的白点的距离

    每个节点开个(multiset)维护下虚子树内白色点的最小距离

    inline int fir(int x)
    {
    	return (!q[x].empty())?(*q[x].begin()):inf;
    }
    inline void pushup(int x)
    {
    	str[x]=str[son[x][0]]+str[son[x][1]]+1;
    	dp1[x]=min(dp1[son[x][0]],str[son[x][0]]+min(val[x]?0:inf,min(fir(x),dp1[son[x][1]]+1)));
    	dp2[x]=min(dp2[son[x][1]],str[son[x][1]]+min(val[x]?0:inf,min(fir(x),dp2[son[x][0]]+1)));
    }
    

    注意(access)的时候更新(multiset)

    inline void access(int x)
    {
    	for(int y=0;x;x=f[y=x])
    	{
    		splay(x);
    		q[x].insert(dp1[son[x][1]]+1);
    		son[x][1]=y;
    		it=q[x].lower_bound(dp1[son[x][1]]+1);
    		if(it!=q[x].end()&&(*it)==dp1[son[x][1]]+1) q[x].erase(it);
    		pushup(x);
    	}
    }
    

    最后答案是将(x)旋转到根之后的(dp2[x])

    我们在这里选择不(makeroot),因为需要翻转子树很麻烦,修改时直接修改(val[x])的状态然后(pushup(x))

    LOJ558

    包括(link)(cut)操作的维护子树

    注意点就是(reverse)的时候要把(dp1)(dp2)一起交换,同时(cut)的时候必须把连个点都喝边代表的虚点断开,否则边权会随机加到一棵(splay)

    维护染色联通块

    luoguP2173

    每种颜色开一个(LCT),大力维护就行了

    luoguP3703

    我们仍然考虑每个(splay)维护同一种颜色

    (1)操作:其实就是一个(access)操作

    (2)操作:考虑一个节点到根节点的权值,就是这个节点到根节点的虚边数量,但是每次(access)更新时会更新一整个子树,所以我们考虑(dfs)序上建线段树维护,询问时考虑树

    上差分,由于每个颜色都是到根节点的一条链,所以可以直接差分

    (3)操作:(dfs)序上区间最值问题

    QTREE6

    点化边模型,显然暴力操作会被菊花图卡到自闭,我们考虑把每个点的颜色给这个点在树上的父亲边

    (1)号节点没有父边,需要加一个虚拟节点

    变化颜色时将该店与父亲节点的边更换(LCT),这样发现每个连通块中除了根节点都是同一颜色

    查询时输出根节点的右儿子的答案

    奇怪操作

    睡觉困难综合症

    四个状态,(0)从根走到当前,(1)从根走到当前,(0)从当前到根,(1)从当前到根

    合并的式子是

    t0=(~x.t0&y.t0)|(x.t0&y.t1);
    t1=(~x.t1&y.t0)|(x.t1&y.t1);
    

    对于(0)起始,就是前一段是(0)的位走后一段(0)起始的答案或上前一段是(1)的位走后一段(1)起始的答案,(1)起始同理

    没了

    UOJ207

    考虑到对于一段路径((x,y)),如果所有路径都经过((x,y)),那么以(x)为根,必然都有且只有一个端点在(y)子树内

    每条路径(rand)一个权值出来,将路径的两个端点异或上这个权值,(split(x,y))之后判断(x)子树异或和是否等于所有边权异或和

    luoguP3348

    逐个操作分析。。

    (1)操作,显然对于所有树都长一个节点是无所谓的

    (2)操作就讲究了,会发现(l)(l-1)颗树的区别只是一大堆节点长哪上面了,转移一大堆节点我们可以套路的弄个虚点出来,把虚点连生长节点下面,生长的时候长虚点下面,更

    改生长节点的时候把虚点换个位置就行了

    查询:规定了根节点的情况下并不能换根,考虑树上差分,对于虚点点权应该为(0),这里有个小技巧:(access)(lca)

    (access(x)),再(access(y)),最后一次操作的(y)节点就是(lca)

    luoguP4338

    考虑每个点的贡献,对于一个点来说,最优的操作方式肯定是一个每个子树内的点交替(access),因为连续两个同一子树内的点(access)不对答案作出贡献

    然而有可能某个子树点数过大导致无法实现。

    具体来说,一个点对答案的贡献是(min{S_x-1,2*(S_x-max{S_{son_x}})})

    (max{S_{son_x}}>frac{S_x+1}{2})(min)取后面

    但是我们还有修改操作

    对于一个点(a_i+w),能影响的只有这个点到根的路径,如果路径中本身就有些点子树过大,那么是不用修改的

    哪些点用修改呢?就是将整棵树重链剖分后的轻边的父节点,这些点不超过(logn)

    证明完复杂度我们可以用(lct)(access)来完成对路径上虚边的判断

    一些细节可以参照(fAKe_Hu)(code)。。。

    在美妙的数学王国中畅游

    乱七八糟的东西不好维护,考虑每个点维护一个多项式

    所以我们把(e^{ax+b})(sin(ax+b))泰勒展开一下子变成多项式维护起来

    然后就基本裸(lct)

  • 相关阅读:
    JavaScript自定义事件
    用Java构建一个简单的WebSocket聊天室
    PHP实现支付宝小程序用户授权的工具类
    jq ajax超时设置
    gulp使用笔记
    vue学习—组件的定义注册
    echarts设置线条粗细
    求js数组的最大值和最小值
    js删除数组中的 "NaN"
    jq方法(end)
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12375608.html
Copyright © 2011-2022 走看看