洛谷P4219 [BJOI2014]大融合(LCT,Splay)

LCT维护子树信息的思路总结与其它问题详见我的LCT总结

思路分析

动态连边,LCT题目跑不了了。然而这题又有点奇特的地方。

我们分析一下,查询操作就是要让我们求出砍断这条边后,x和y各自子树大小的乘积。

掌握了LCT如何维护虚子树信息和后,做法就很清晰了。split(x,y)后,输出x的虚子树和+1与y的虚子树和+1的乘积;或者,(以y为根)输出x的子树总和与y的子树总和减去x的子树总和的乘积。

代码如下(这次我试着写了一个单旋"Spaly",好像常数还小不少。。。。。。

#include<cstdio>
#include<cstdlib>
#define R register int
#define I inline void
const int N=100009;
int f[N],c[N][2],si[N],s[N];
bool r[N];
#define lc c[x][0]
#define rc c[x][1]
inline bool nroot(R x){return c[f[x]][0]==x||c[f[x]][1]==x;}
I pushup(R x){
    s[x]=s[lc]+s[rc]+si[x]+1;
}
I pushdown(R x){
    if(r[x]){
        R t=lc;lc=rc;rc=t;
        r[lc]^=1;r[rc]^=1;r[x]=0;
    }
}
I pushall(R x){
    if(nroot(x))pushall(f[x]);
    pushdown(x);
}
I rotate(R x){
    R y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
    if(nroot(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;
    f[w]=y;f[y]=x;f[x]=z;
    pushup(y);
}
I splay(R x){//请忽略这个spaly
    pushall(x);
    while(nroot(x))rotate(x);
    pushup(x);
}
I access(R x){
    for(R y=0;x;x=f[y=x]){
        splay(x);
        si[x]+=s[rc];
        si[x]-=s[rc=y];
        //pushup(x);试着去掉,发现对答案无影响
    }
}
I makeroot(R x){
    access(x);splay(x);
    r[x]^=1;
}
I split(R x,R y){
    makeroot(x);
    access(y);splay(y);
}
I link(R x,R y){
    split(x,y);
    si[f[x]=y]+=s[x];
    pushup(y);
}//LCT模板到此结束
#define G ch=getchar()
#define gc G;while(ch<‘-‘)G
#define in(z) gc;z=ch&15;G;while(ch>‘-‘)z*=10,z+=ch&15,G;
int main(){
    register char ch;
    register bool fl;
    R n,q,u,v;
    in(n);in(q);
    for(R i=1;i<=n;++i)s[i]=1;
    while(q--){
        gc;fl=ch==‘A‘;in(u);in(v);
        if(fl)link(u,v);
        else{
            split(u,v);
            printf("%lld\n",(long long)(si[u]+1)*(si[v]+1));//可以换成上面提到的另一种
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/flashhu/p/8423326.html

时间: 2024-11-03 20:37:59

洛谷P4219 [BJOI2014]大融合(LCT,Splay)的相关文章

洛谷P4219 - [BJOI2014]大融合

Portal Description 初始有\(n(n\leq10^5)\)个孤立的点,进行\(Q(Q\leq10^5)\)次操作: 连接边\((u,v)\),保证\(u,v\)不连通. 询问有多少条简单路径经过边\((u,v)\). Solution 加边用lct,询问结果相当于\(p\)为根时的\((siz[p]-siz[q])\times siz[q]\). 那么如何用lct维护子树大小呢?维护\(isiz[p]\)表示\(p\)在lct上的虚子树大小,\(siz[p]\)表示\(isiz

P4219 [BJOI2014]大融合(LCT)

P4219 [BJOI2014]大融合 对于每个询问$(u,v)$所求的是 ($u$的虚边子树大小+1)*($v$的虚边子树大小+1) 于是我们再开个$si[i]$数组表示$i$的虚边子树大小,维护一下就好辣 #include<iostream> #include<cstdio> #include<cstring> using namespace std; inline void Swap(int &a,int &b){a^=b^=a^=b;} void

【bzoj4530】[Bjoi2014]大融合 LCT维护子树信息

题目描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量. 例如,在上图中,现在一共有了5条边.其中,(3,8)这条边的负载是6,因为有六条简单路径2-3-8,2-3-8-7,3-8,3-8-7,4-3-8,4-3-8-7路过了(3,8). 现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的询问. 输入 第一行包含两个整数N,Q,表示星球的

Luogu4219 BJOI2014 大融合 LCT

传送门 题意:写一个数据结构,支持图上连边(保证图是森林)和询问一条边两端的连通块大小的乘积.$\text{点数.询问数} \leq 10^5$ 图上连边,$LCT$跑不掉 支持子树$size$有点麻烦.我们需要虚子树的$size$和(实子树的可以直接$pushup$),那么我们对于每一个点就去维护其虚子树的$size$和,那么每一个点的子树和就是可以维护的了.可以知道只有$link$和$access$操作会修改虚子树和(其他都在实链上进行操作),稍微加一点东西就行了.相对来说还是比较裸. 注意

[BJOI2014]大融合 LCT维护子树信息

Code: #include <cstdio> #include <algorithm> #include <cstring> #include <string> using namespace std; void setIO(string a){freopen((a+".in").c_str(),"r",stdin);} #define maxn 100009 #define ll long long int n,q

P4219 [BJOI2014]大融合

传送门 动态维护森林 显然考虑 $LCT$ 但是发现询问求的是子树大小,比较不好搞 维护 $sum[x]$ 表示节点 $x$ 的子树大小,$si[x]$ 表示 $x$ 的子树中虚儿子的子树大小和 那么 $pushup$ 可以这样写: inline void pushup(int x) { sum[x]=sum[c[x][0]]+sum[c[x][1]]+si[x]+1; } 考虑什么时候 $si$ 会变 首先对于 $rotate,splay$ 因为都是对一条实链搞,所以对虚边没影响 然后考虑 $

LuoguP4219 [BJOI2014]大融合(LCT)

早上考试想用\(LCT\)维护联通块\(size\),现在才发现\(LCT\)的\(size\)有虚实之分 \(Link\)与\(Acess\)中虚实变,干他丫的 \(Splay\)中只是相对关系,没有虚实变,因此不搞它 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define R(a,b,c) fo

BZOJ:4530: [Bjoi2014]大融合

4530: [Bjoi2014]大融合 拿这题作为lct子树查询的练手.本来以为这会是一个大知识点,结果好像只是一个小技巧? 多维护一个虚边连接着的子树大小即可. #include<cstdio> #include<cstring> #include<algorithm> #define MN 210010 using namespace std; int p,ca,f; inline int read(){ p=0;ca=getchar();f=1; while(ca

BJOI2014 大融合

3766. [BJOI2014]大融合 (Standard IO) Time Limits: 1000 ms  Memory Limits: 262144 KB Description 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树.这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量. 例如,在上图中,现在一共有了5条边.其中,(3,8)这条边的负载是6,因为有六条简单路径2-3-8,2-3-8-7,3-8