[CF855G]Harry Vs Voldemort

题目大意:

一棵\(n(n\le10^5)\)个结点的树,\(q(q\le10^5)\)次操作,每次增加一条新边。每次操作后,你需要统计形如\((u,v,w)\)的三元组的数量,使得\(u,v,w\)都不相同,并存在两条分别\(u\)到\(w\)和\(v\)到\(w\)的路径,使得两条路径没有共同边。

思路:

每次加边相当于将两个顶点之间的所有边缩成了一个边双连通分量。

考虑三元组\((u,v,w)\):

  1. \(u,v,w\)均在同一个边双中;
  2. \(u,v\)中有一个在与\(w\)相同的边双中;
  3. \(u,v,w\)均在不同的边双中。

对三种情况分别讨论即可。

对于情况2,3,只需维护边双大小\(size[u]\);对于情况1,还需维护子树大小\(tsize[u]\),和\(u,v\)分布在相同(或不同)子树中的方案数。

边双缩点可以用并查集实现。

时间复杂度\(\mathcal O(n\alpha(n))\)。

源代码:

#include<cstdio>
#include<cctype>
#include<vector>
#include<numeric>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
typedef long long int64;
const int N=1e5+1;
std::vector<int> e[N];
inline void add_edge(const int &u,const int &v) {
e[u].push_back(v);
e[v].push_back(u);
}
int64 ans,val[N],tmp[N];
int n,par[N],dep[N],size[N],tsize[N];
struct DisjointSet {
int anc[N];
void reset(const int &n) {
std::iota(&anc[1],&anc[n]+1,1);
}
int find(const int &x) {
return x==anc[x]?x:anc[x]=find(anc[x]);
}
void merge(const int &x,const int &y) {
anc[find(x)]=find(y);
}
bool same(const int &x,const int &y) {
return find(x)==find(y);
}
};
DisjointSet djs;
void dfs(const int &x,const int &par) {
::par[x]=par;
dep[x]=dep[par]+1;
size[x]=tsize[x]=1;
for(int y:e[x]) {
if(y==par) continue;
dfs(y,x);
tsize[x]+=tsize[y];
}
}
int64 calc(const int &x) {
int64 ans=0;
ans+=1ll*size[x]*(size[x]-1)*(size[x]-2);//XXX
ans+=2ll*size[x]*(size[x]-1)*(n-size[x]);//XX-Y & Y-XX
ans+=1ll*(n-size[x])*(n-size[x])*size[x];
for(int y:e[x]) {//Y-X-Z & Z-X-Y
if(djs.same(x,y)) continue;
const int z=djs.find(y);
const int sz=y==par[x]?n-tsize[x]:tsize[z];
ans-=1ll*sz*sz*size[x];
tmp[x]+=1ll*sz*sz;
}
return val[x]=ans;
}
int64 calc2(const int &x) {
int64 ans=0;
ans+=1ll*size[x]*(size[x]-1)*(size[x]-2);//XXX
ans+=2ll*size[x]*(size[x]-1)*(n-size[x]);//XX-Y & Y-XX
ans+=1ll*(n-size[x])*(n-size[x])*size[x];//Y-X-Z & Z-X-Y
ans-=tmp[x]*size[x];
return val[x]=ans;
}
void merge(int u,int v) {
u=djs.find(u);
v=djs.find(v);
while(u!=v) {
if(dep[u]<dep[v]) std::swap(u,v);
const int w=djs.find(par[u]);
tmp[w]-=1ll*tsize[u]*tsize[u];
tmp[w]+=tmp[u]-1ll*(n-tsize[u])*(n-tsize[u]);
ans-=val[u];
size[w]+=size[u];
djs.merge(u,w);
u=w;
}
ans-=val[u];
ans+=calc2(u);
}
int main() {
n=getint();
for(register int i=1;i<n;i++) {
add_edge(getint(),getint());
}
djs.reset(n);
dfs(1,0);
for(register int x=1;x<=n;x++) {
ans+=calc(x);
}
printf("%lld\n",ans);
const int q=getint();
for(register int i=0;i<q;i++) {
merge(getint(),getint());
printf("%lld\n",ans);
}
return 0;
}

[CF855G]Harry Vs Voldemort的更多相关文章

  1. cdoj 71 I am Lord Voldemort 水题

    I am Lord Voldemort Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/ ...

  2. 【题解】CF#855 G-Harry Vs Voldemort

    个人感觉挺有意思的,然而被颜神D无聊惹(- ̄▽ ̄)- 这题我们可以首先试图去统计以每一个点作为 w 点所能对答案造成的贡献是多少.不难发现,当且仅当 u 和 v 都在 w 所在边双的一侧的时候不能构成 ...

  3. Solution -「CF 855G」Harry Vs Voldemort

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个点的树和 \(q\) 次加边操作.求出每次操作后,满足 \(u,v,w\) 互不相等,路径 \((u,w ...

  4. 非关系型数据库(NoSql)

    最近了解了一点非关系型数据库,刚刚接触,觉得这是一个很好的方向,对于大数据 方面的处理,非关系型数据库能起到至关重要的地位.这里我主要是整理了一些前辈的经验,仅供参考. 关系型数据库的特点 1.关系型 ...

  5. PayPal高级工程总监:读完这100篇论文 就能成大数据高手(附论文下载)

    100 open source Big Data architecture papers for data professionals. 读完这100篇论文 就能成大数据高手 作者 白宁超 2016年 ...

  6. Index

    我主要在研究.NET/C# 实现 PC IMERP 和 Android IMERP ,目的在解决企业通信中遇到的各类自动化问题   分布式缓存框架: Microsoft Velocity:微软自家分布 ...

  7. Day12-mysql&&redis

    1. 数据库介绍 什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据.我们也可以将数 ...

  8. 1、NoSQL概述

    最近抽时间把Redis学了一下,所以就在网上找了一些资料.然后找到尚硅谷-周阳老师的视频教程,觉得里面的讲的挺好.所以就把他视频当中的资料教程整理出来. 单机MySQL的美好时代 在90年代,一个网站 ...

  9. NOSQL数据模型和CAP原理

    NOSQL数据模型和CAP原理 http://blog.sina.com.cn/s/blog_7800d9210100t33v.html 我本来一直觉得NoSQL其实很容易理解的,我本身也已经对NoS ...

随机推荐

  1. MAC 添加Jmeter环境变量

    vim ./bash_profile JMETER_HOME=/Users/finup/apache-jmeter-5.1.1 CLASSPATH=$JAVA_HOME/lib/tools.jar:$ ...

  2. 启动Spring boot项目报错:java.lang.IllegalArgumentException: LoggerFactory is not a Logback

    java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on t ...

  3. a标签中target属性为“_blank”时存在安全问题

    今天看到一个比较有意思的洞,虽然不够严重,但是却普遍存在各大src中 熟悉js的朋友都应该知道当我们在调用window下的open方法创建一个新窗口的同时,我们可以获得一个创建窗口的opener句柄, ...

  4. tkinter 按钮响应函数传值

    tkinter 中的Button组件的响应函数如何传入参数,可能非常困扰新手,这里记录一下. 步骤: 1. 写好响应函数(形参设置好) 2. 在Button command 设置形式:command ...

  5. c# Queue 类

  6. nginx的压缩、https加密实现、rewrite、常见盗链配置

    Nginx 压缩功能 ngx_http_gzip_module #ngx_http_gzip_module 用gzip方法压缩响应数据,节约带宽 #启用或禁用gzip压缩,默认关闭 gzip on | ...

  7. Redis锁机制的几种实现方式

    1. redis加锁分类 redis能用的的加锁命令分表是INCR.SETNX.SET 2. 第一种锁命令INCR 这种加锁的思路是, key 不存在,那么 key 的值会先被初始化为 0 ,然后再执 ...

  8. 用java刷剑指offer(数字在排序数组中出现的次数)

    题目描述 统计一个数字在排序数组中出现的次数. 牛客网链接 java代码 //看见有序就用二分法 public class Solution { public int GetNumberOfK(int ...

  9. python高级特性-生成器

    在python中一边循环一边计算的机制成为生成器(generator) 在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行. 生成list > ...

  10. python中的exec和eval

    exec 描述 exec 执行储存在字符串或文件中的 Python 语句,相比于 eval,exec可以执行更复杂的 Python 代码. 返回值 exec 返回值永远为 None. 需要说明的是在 ...