【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=2888

【题目大意】

  不断加边,问每个连通块的重心到其它点的距离和的和

【题解】

  启发式合并LCT,通过维护等差数列的首项和公差
  来实现保存子树内所有节点到这个节点的距离之和。

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=40010;
namespace Heuristic_LCT{
int ans,g[N],v[N<<1],nxt[N<<1],ed;
int f[N],son[N][2],val[N],tag[N],sum[N],ts[N],td[N],size[N],tmp[N];
bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
void add1(int x,int p){if(!x)return;val[x]+=p;tag[x]+=p;}
void add2(int x,int s,int d){if(!x)return;sum[x]+=s+size[son[x][1]]*d;ts[x]+=s;td[x]+=d;}
void pb(int x){
if(tag[x]){
add1(son[x][0],tag[x]);
add1(son[x][1],tag[x]);
tag[x]=0;
}
if(td[x]){
add2(son[x][0],ts[x]+(size[son[x][1]]+1)*td[x],td[x]);
add2(son[x][1],ts[x],td[x]);
ts[x]=td[x]=0;
}
}
void up(int x){size[x]=size[son[x][0]]+size[son[x][1]]+1;}
void rotate(int x){
int y=f[x],w=son[y][1]==x;
son[y][w]=son[x][w^1];
if(son[x][w^1])f[son[x][w^1]]=y;
if(f[y]){
int z=f[y];
if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x;
}f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y);
}
void splay(int x){
int s=1,i=x,y;tmp[1]=i;
while(!isroot(i))tmp[++s]=i=f[i];
while(s)pb(tmp[s--]);
while(!isroot(x)){
y=f[x];
if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
rotate(x);
}up(x);
}
void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);}
int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;}
void addleaf(int x,int y){
f[y]=x,son[y][0]=son[y][1]=val[y]=tag[y]=sum[y]=ts[y]=td[y]=0,size[y]=1;
x=root(x),access(y),splay(x),add1(x,1),add2(x,0,1);
for(y=son[x][1];son[y][0];y=son[y][0]);splay(y);
int vx=val[x],vy=val[y];
if(vy*2>vx){
val[y]=vx,val[x]-=vy;
sum[x]-=sum[y]+vy,sum[y]+=sum[x]+vx-vy;
access(y),splay(x),son[x][0]=y,son[x][1]=0;
}
}
void dfs(int x,int y){
addleaf(y,x);
for(int i=g[x];i;i=nxt[i])if(v[i]!=y)dfs(v[i],x);
}
void addedge(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void link(int x,int y){
int X=root(x),Y=root(y);
ans-=sum[X]+sum[Y];
if(val[X]<val[Y])swap(x,y);
dfs(y,x),addedge(x,y),addedge(y,x);
ans+=sum[root(x)];
}
void Initialize(){
ans=0;
memset(f,0,sizeof(f));
memset(son,0,sizeof(son));
memset(ts,0,sizeof(ts));
memset(td,0,sizeof(td));
memset(tag,0,sizeof(tag));
}
}
int n,m,x,y;
char op[5];
int main(){
using namespace Heuristic_LCT;
Initialize();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)val[i]=size[i]=1;
while(m--){
scanf("%s",op);
if(op[0]=='A')scanf("%d%d",&x,&y),link(x,y);
if(op[0]=='Q')printf("%d\n",ans);
}return 0;
}

BZOJ 2888 资源运输(启发式合并LCT)的更多相关文章

  1. BZOJ 4668: 冷战 并查集启发式合并/LCT

    挺好想的,最简单的方法是并查集启发式合并,加暴力跳父亲. 然而,这个代码量比较小,比较好写,所以我写了 LCT,更具挑战性. #include <cstdio> #include < ...

  2. [bzoj3123] [SDOI2013]森林 主席树+启发式合并+LCT

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  3. BZOJ 3123 [SDOI2013] 森林 - 启发式合并 主席树

    Description 给你一片森林, 支持两个操作: 查询$x$到$y$的$K$大值,  连接两棵树中的两个点 Solution 对每个节点$x$动态开权值线段树, 表示从$x$到根节点路径上权值出 ...

  4. BZOJ 3123 主席树 启发式合并

    思路: 主席树 搞树上的k大 x+y-lca(x,y)-fa(lca(x,y)) 按照size小树往大树上插 启发式合并 n*log^2n的 搞定~ //By SiriusRen #include & ...

  5. BZOJ 4919 (树上LIS+启发式合并)

    题面 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你需要选择尽可能多的节点,满足大根堆的性质:对于任意两个点i, ...

  6. BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay

    Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询 ...

  7. 【BZOJ-2888】资源运输 LCT + 启发式合并

    2888: 资源运输 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 63  Solved: 33[Submit][Status][Discuss] D ...

  8. BZOJ2888 资源运输(LCT启发式合并)

    这道题目太神啦! 我们考虑他的每一次合并操作,为了维护两棵树合并后树的重心,我们只好一个一个的把节点加进去.那么这样一来看上去似乎就是一次操作O(nlogn),但是我们拥有数据结构的合并利器--启发式 ...

  9. BZOJ.3510.首都(LCT 启发式合并 树的重心)

    题目链接 BZOJ 洛谷 详见这. 求所有点到某个点距离和最短,即求树的重心.考虑如何动态维护. 两棵子树合并后的重心一定在两棵树的重心之间那条链上,所以在合并的时候用启发式合并,每合并一个点检查sz ...

随机推荐

  1. 【洛谷 P1073】 最优贸易 (Tarjan缩点+拓扑排序)

    题目链接 先\(Tarjan\)缩点,记录每个环内的最大值和最小值. 然后跑拓扑排序,\(Min[u]\)表示到\(u\)的最小值,\(ans[u]\)表示到\(u\)的答案,\(Min\)和\(an ...

  2. js_页面关闭beforeunload事件

    做圆桌爆文公众号的时候,需要对阅读的文章进行时间统计.是这个公众号的核心功能,客户把文章转发到朋友圈或者转给朋友,记录谁阅读此文章和阅读时长进行记录,从而展示给客户. 功能点是,关闭页面时触发事件,请 ...

  3. 8.0docker的客户端和守护进程

    C/S 链接的方式 unix:///var/run/docker.sock 默认的 tcp://host:port fd://socketfd 在linux上进行socket 模拟 nc -U /va ...

  4. Java回收方法区中回收的类

    回收的类必须满足下面三个条件才能算是“无用的类” 1.该类所有的实例都已经被回收,也就是说Java堆中不存在该类的任何实例: 2.加载该类的ClassLoader已经被回收: 3.该类对应的java. ...

  5. 自动化测试===uiautomator2类似appium

    项目地址:https://github.com/openatx/uiautomator2 http://mp.weixin.qq.com/s/YKxwW-pL603Fll3QIWapVw https: ...

  6. redis cluster 实现

    Redis cluster是一个redis官方提供的集群功能,集群节点最小3个节点,配置比较多,记录下来,以供下次使用.我在这使用的redis 4.0.6. 因为最新的ruby redis扩展需要ru ...

  7. 2017多校第6场 HDU 6096 String AC自动机

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6096 题意:给了一些模式串,然后再给出一些文本串的不想交的前后缀,问文本串在模式串的出现次数. 解法: ...

  8. 将MongoDB安装成为Windows服务

    使用以下命令将MongoDB安装成为Windows服务.笔者的MongoDB目录为D:\Program Files\mongodb 切换到D:\Program Files\mongodb\bin> ...

  9. 阿里云Centos等更新源设置成阿里源方法。

    https://help.aliyun.com/knowledge_detail/5974184.html ---------------------------------------------- ...

  10. css文件放在头部的原因

    我在博问上发的一个这个问题 然后有人这样回复我的 我感觉很有道理的样子 所以我放上来了 这样会先加载css的样式,在渲染dom的时候已经知道了自己的样式了,所以一次渲染成功 如果css放在底部,那么需 ...