易知所求的是两棵子树大小的乘积。先建出最后所得到的树,求出dfs序和子树大小。之后考虑如何在动态加边过程中维护子树大小。这个可以用树剖比较简单的实现,但还有一种更快更优美的做法就是线段树合并。对每个点开权值线段树,维护当前时刻这棵点为根的子树中,已经和其相连的点的dfs序情况。合并时直接将表示两棵子树的线段树合并,查询在整棵子树中查询某段dfs序区间。

也可以在线地用lct维护子树,并不会。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 100010
int n,q,fa[N],dfn[N],p[N],root[N],size[N],t=,cnt=;
struct data{int x,y,op;
}Q[N];
struct data2{int to,nxt;
}edge[N<<];
struct data3{int l,r,x;
}tree[N<<];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void dfs(int k)
{
dfn[k]=++cnt;size[k]=;
for (int i=p[k];i;i=edge[i].nxt)
if (!dfn[edge[i].to])
{
dfs(edge[i].to);
size[k]+=size[edge[i].to];
}
}
void add(int &k,int l,int r,int x)
{
if (!k) k=++cnt;
tree[k].x++;
if (l==r) return;
int mid=l+r>>;
if (x<=mid) add(tree[k].l,l,mid,x);
else add(tree[k].r,mid+,r,x);
}
int merge(int x,int y,int l,int r)
{
if (!x||!y) return x|y;
tree[x].x+=tree[y].x;
int mid=l+r>>;
tree[x].l=merge(tree[x].l,tree[y].l,l,mid),
tree[x].r=merge(tree[x].r,tree[y].r,mid+,r);
return x;
}
int query(int k,int l,int r,int x,int y)
{
if (!k) return ;
if (l==x&&r==y) return tree[k].x;
int mid=l+r>>;
if (y<=mid) return query(tree[k].l,l,mid,x,y);
else if (x>mid) return query(tree[k].r,mid+,r,x,y);
else return query(tree[k].l,l,mid,x,mid)+query(tree[k].r,mid+,r,mid+,y);
}
int main()
{
freopen("bzoj4530.in","r",stdin);
freopen("bzoj4530.out","w",stdout);
n=read(),q=read();
for (int i=;i<=n;i++) fa[i]=i;
for (int i=;i<=q;i++)
{
char c=getchar();
while (c!='A'&&c!='Q') c=getchar();
Q[i].x=read(),Q[i].y=read();
if (c=='A') Q[i].op=,addedge(Q[i].x,Q[i].y),addedge(Q[i].y,Q[i].x);else Q[i].op=;
}
for (int i=;i<=n;i++)
if (!dfn[i]) dfs(i);
cnt=;
for (int i=;i<=n;i++)
add(root[i],,n,dfn[i]);
for (int i=;i<=q;i++)
{
if (dfn[Q[i].x]>dfn[Q[i].y]) swap(Q[i].x,Q[i].y);
int p=find(Q[i].x);
if (Q[i].op==)
{
fa[Q[i].y]=p;
root[p]=merge(root[p],root[Q[i].y],,n);
}
else
{
int s=query(root[p],,n,dfn[Q[i].y],dfn[Q[i].y]+size[Q[i].y]-),t=tree[root[p]].x;
printf("%lld\n",1ll*s*(t-s));
}
}
fclose(stdin);fclose(stdout);
return ;
}

BZOJ4530 BJOI2014大融合(线段树合并+并查集+dfs序)的更多相关文章

  1. 【BZOJ-4530】大融合 线段树合并

    4530: [Bjoi2014]大融合 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 280  Solved: 167[Submit][Status] ...

  2. BZOJ4399魔法少女LJJ——线段树合并+并查集

    题目描述 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了LJJ感叹道“这里真是个迷人的绿色世界,空气清新.淡雅,到处散发着醉人的奶浆味: ...

  3. [BZOJ4530][Bjoi2014]大融合 LCT + 启发式合并

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

  4. Educational Codeforces Round 51 (Rated for Div. 2) G. Distinctification(线段树合并 + 并查集)

    题意 给出一个长度为 \(n\) 序列 , 每个位置有 \(a_i , b_i\) 两个参数 , \(b_i\) 互不相同 ,你可以进行任意次如下的两种操作 : 若存在 \(j \not = i\) ...

  5. Codeforces.1051G.Distinctification(线段树合并 并查集)

    题目链接 \(Description\) 给定\(n\)个数对\(A_i,B_i\).你可以进行任意次以下两种操作: 选择一个位置\(i\),令\(A_i=A_i+1\),花费\(B_i\).必须存在 ...

  6. BZOJ2733[HNOI2012]永无乡——线段树合并+并查集+启发式合并

    题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达 ...

  7. 洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)

    题目描述 永无乡包含 nnn 座岛,编号从 111 到 nnn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nnn 座岛排名,名次用 111 到 nnn 来表示.某些岛之间由巨大的桥连接, ...

  8. 线段树合并+并查集 || BZOJ 2733: [HNOI2012]永无乡 || Luogu P3224 [HNOI2012]永无乡

    题面:P3224 [HNOI2012]永无乡 题解: 随便写写 代码: #include<cstdio> #include<cstring> #include<iostr ...

  9. 【BZOJ2733】永无乡(线段树,并查集)

    [BZOJ2733]永无乡(线段树,并查集) 题面 BZOJ 题解 线段树合并 线段树合并是一个很有趣的姿势 前置技能:动态开点线段树 具体实现:每次合并两棵线段树的时候,假设叫做\(t1,t2\), ...

随机推荐

  1. ASP.NET Core MVC中Controller的Action,默认既支持HttpGet,又支持HttpPost

    我们知道ASP.NET Core MVC中Controller的Action上可以声明HttpGet和HttpPost特性标签,来限制可以访问Action的Http请求类型(GET.POST等). 那 ...

  2. Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core"

    问题描述 今天写jsp的时候想用JSTL的一些标签,但是引用的时候碰到这个问题. 解决办法 一.看是否引用jstl.jar包,如果没有,则可以下载相应版本的jstr.jar包,并放入WEB-INF的l ...

  3. 【php增删改查实例】第十一节 - 部门管理模块(编辑功能)

    9. 编辑部门功能的实现 思路:只允许用户勾选一条数据,点击编辑按钮,会跳出一个和新增数据类似的对话框.然后,用户可以修改部门名称和部门编码.点击保存按钮,提示修改成功. 9.1 前台代码编写 < ...

  4. 51nod 抽卡大赛

    抽卡大赛 链接 分析: $O(n^4)$的做法比较好想,枚举第i个人选第j个,然后背包一下,求出有k个比他大的概率. 优化: 第i个人,选择一张卡片,第j个人选的卡片大于第i个人的概率是$p_j$,那 ...

  5. Roslyn入门(一)-C#语法分析

    演示环境 Visual Studio 2017 .NET Compiler Platform SDK 简介 今天,Visual Basic和C#编译器是黑盒子:输入文本然后输出字节,编译管道的中间阶段 ...

  6. Spring Zuul 性能调优,如何提升平均响应时间200% ?

    最近负责公司的 Gateway 项目,我们用 Spring Zuul 来做 HTTP 转发,但是发现请求多的时候,AWS 的健康检查就失败了,但是实际上程序还在跑,在日志上也没有任何东西错误打印出来出 ...

  7. 开启C语言的学习之门

    本人是一枚工业界的码农,为了职业道路越来越宽广决定向上位机方面进军,C语言曾经在大学里面学过点皮毛但是离应用远远不够,尽量每天在工作之余更新自己学习的进度,同时也希望有大神能给予在编程道路上的指导,话 ...

  8. Windows 10 中 VMware 要求禁用 Device Guard 问题

    今天在打开虚拟机的时候,突然出现下面这个错误.网上给了很多教程,基本上都是禁用 Device Guard 和关闭 Hyper-v,博主按照其方法操作,依旧出现下面错误.后来经过不懈努力,终于找到解决办 ...

  9. ireportdesigner下载页面

    iReport主页:http://community.jaspersoft.com/project/ireport-designer iReport下载地址:http://sourceforge.ne ...

  10. 分布式监控系统Zabbix-批量添加聚合图形

    之前部署了Zabbix(3.4.4版本)监控环境,由于主机比较多,分的主机组也比较多,添加聚合图形比较麻烦,故采用python脚本进行批量添加聚合图形.脚本下载地址:https://pan.baidu ...