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[p]\)加上在辅助树上的实子树大小(子树大小也包括子树的虚子树和实子树)。当\(p=rt\)或\(p\)没有实子树时,\(siz[p]\)等于其原树上的子树大小。

如何维护\(isiz\)呢?只有当树的虚实划分变化时,\(isiz\)才会变化,也就是accesslinkaccess(p)中有一句ch[p][1]=q,说明\(ch[p][1]\)变为虚子树,\(q\)变为实子树,则isiz[p]+=siz[ch[p][1]]-siz[q]link(p,q)将\(p\)变为\(q\)的虚子树,因此\(q\)到\(q\)的根的\(isiz\)都要改变;因为不好实现所以makeRt(q)之后再连接,并isiz[q]+=siz[p]

询问时,只要makeRt(p),access(q),splay(q),此时\(q=rt\),\(p\)没有实子树,\(siz\)均正确。

时间复杂度\(O(Qlogn)\)。

Code

//[BJOI2014]大融合
#include <cstdio>
#include <algorithm>
using namespace std;
int read()
{
int x=0; char ch=getchar();
while(ch<'0'||'9'<ch) ch=getchar();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
int const N=1e5+10;
int n,Q;
int fa[N],ch[N][2],siz[N],isiz[N]; bool rev[N];
int wh(int p) {return p==ch[fa[p]][1];}
int notRt(int p) {return p==ch[fa[p]][wh(p)];}
void rever(int p) {rev[p]^=1; swap(ch[p][0],ch[p][1]);}
void update(int p) {siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+isiz[p]+1;}
void pushdw(int p) {if(rev[p]) rever(ch[p][0]),rever(ch[p][1]),rev[p]=false;}
void rotate(int p)
{
int q=fa[p],r=fa[q],w=wh(p);
fa[p]=r; if(notRt(q)) ch[r][wh(q)]=p;
fa[ch[q][w]=ch[p][w^1]]=q;
fa[ch[p][w^1]=q]=p;
update(q),update(p);
}
void pushdwRt(int p) {if(notRt(p)) pushdwRt(fa[p]); pushdw(p);}
void splay(int p)
{
pushdwRt(p);
for(int q=fa[p];notRt(p);rotate(p),q=fa[p]) if(notRt(q)) rotate(wh(p)^wh(q)?p:q);
}
void access(int p) {for(int q=0;p;q=p,p=fa[p]) splay(p),isiz[p]+=siz[ch[p][1]]-siz[q],ch[p][1]=q,update(p);}
void makeRt(int p) {access(p),splay(p),rever(p);}
void link(int p,int q) {makeRt(p),makeRt(q); fa[p]=q,isiz[q]+=siz[p]; update(q);}
long long query(int p,int q) {makeRt(p),access(q),splay(q); return (long long)siz[p]*(siz[q]-siz[p]);}
int main()
{
n=read(),Q=read();
for(int i=1;i<=n;i++) siz[i]=1;
for(int i=1;i<=Q;i++)
{
char opt[5]; scanf("%s",opt);
int u=read(),v=read();
if(opt[0]=='A') link(u,v);
else printf("%lld\n",query(u,v));
}
return 0;
}

P.S.

比Icefox短了20行!

洛谷P4219 - [BJOI2014]大融合的更多相关文章

  1. 洛谷 P4219 [BJOI2014]大融合 解题报告

    P4219 [BJOI2014]大融合 题目描述 小强要在\(N\)个孤立的星球上建立起一套通信系统.这套通信系统就是连接\(N\)个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的 ...

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

    LCT维护子树信息的思路总结与其它问题详见我的LCT总结 思路分析 动态连边,LCT题目跑不了了.然而这题又有点奇特的地方. 我们分析一下,查询操作就是要让我们求出砍断这条边后,x和y各自子树大小的乘 ...

  3. 洛谷P4219 [BJOI2014]大融合(LCT)

    LCT维护子树信息的思路总结与其它问题详见我的LCT总结 思路分析 动态连边,LCT题目跑不了了.然而这题又有点奇特的地方. 我们分析一下,查询操作就是要让我们求出砍断这条边后,x和y各自子树大小的乘 ...

  4. 洛谷 P4219 [BJOI2014]大融合

    查询,就相当于先删去这条边,然后查询边的两个端点所在连通块大小,乘起来得到答案,然后再把边加回去 可以用线段树分治做 #pragma GCC optimize("Ofast") # ...

  5. 洛谷4219 BJOI2014大融合(LCT维护子树信息)

    QWQ 这个题目是LCT维护子树信息的经典应用 根据题目信息来看,对于一个这条边的两个端点各自的\(size\)乘起来,不过这个应该算呢? 我们可以考虑在LCT上多维护一个\(xv[i]\)表示\(i ...

  6. P4219 [BJOI2014]大融合(LCT)

    P4219 [BJOI2014]大融合 对于每个询问$(u,v)$所求的是 ($u$的虚边子树大小+1)*($v$的虚边子树大小+1) 于是我们再开个$si[i]$数组表示$i$的虚边子树大小,维护一 ...

  7. P4219 [BJOI2014]大融合

    传送门 动态维护森林 显然考虑 $LCT$ 但是发现询问求的是子树大小,比较不好搞 维护 $sum[x]$ 表示节点 $x$ 的子树大小,$si[x]$ 表示 $x$ 的子树中虚儿子的子树大小和 那么 ...

  8. P4219 [BJOI2014]大融合 LCT维护子树大小

    \(\color{#0066ff}{ 题目描述 }\) 小强要在\(N\)个孤立的星球上建立起一套通信系统.这套通信系统就是连接\(N\)个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一 ...

  9. luogu P4219 [BJOI2014]大融合

    题解:原来LCT也能维护子树信息,我太Naive了 用LCT维护当前子树节点个数 具体做法维护siz[x]=当前Splay子树和指向当前Splay子树的虚边所代表的节点个数 auxsiz[x]=指向x ...

随机推荐

  1. Suricata的规则解读(默认和自定义)

    不多说,直接上干货! 见suricata官网 https://suricata.readthedocs.io/en/latest/rules/index.html 一.Suricata的规则所放位置 ...

  2. P3372 【模板】线段树 1 区间查询与区间修改

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个 ...

  3. 【经验总结】北邮OJ

    90. 字符串转换 时间限制 1000 ms 内存限制 65536 KB 题目描述 我们将仅由若干个同一小写字母构成的字符串称之为简单串,例如"aaaa"是一个简单串,而" ...

  4. 类似QQ在线离线好友界面

    把头像设置成圆形的代码如下: package com.example.lesson6_11_id19; import android.content.Context; import android.c ...

  5. 自定义Toast的显示位置和显示内容

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  6. 使用colab运行深度学习gpu应用(Mask R-CNN)实践

    1,目的 Google Colaboratory(https://colab.research.google.com)是谷歌开放的一款研究工具,主要用于机器学习的开发和研究.这款工具现在可以免费使用, ...

  7. Qt获取本机IP地址

    Qt获取本机IP地址: Qt版本:4.8.6 #include <QtNetwork/QNetworkInterface.h> QString ipAddr; QList<QHost ...

  8. Selenium私房菜系列--总章

    前言 在这段期间,我一直在找关于服务器的端测试方案,自动化工具等等,无意间我发现了Selenium这个工具.在试用一段时间后,觉得Selenium确实是一个很不错的Web测试工具.在和强大的QTP比较 ...

  9. 获取页面URL两种方式

    以请求http://localhost:8080/doctor/demo?code=1为例 一:用java代码获取 //获取URL中的请求参数.即?后的条件 code=1 String querySt ...

  10. C# 移动控件

    最近要做车牌识别的,不同地区收费标准不一,所以想做个可以移动控件来给客户选择停车场收费条件的.   首先因为要自动排序控件选FlowLayoutPanel做容器,加若干Panel和FlowLayout ...