[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. quartz2.3.0(五)制定错过执行任务的misfire策略,用pause,resume模拟job暂停执行和继续执行

    感谢兄台: <quartz-misfire 错失.补偿执行> misfire定义 misfire:被错过的执行任务策略 misfire重现——CronTrigger job任务类: pac ...

  2. mysql_select 单表查询

    select *         *代表全部   查询多个字段 select  字段1,字段2,字段3   聚合函数  count(*)       统计 select count(*)       ...

  3. Appium_Page object设计模式

    Page object设计模式思维,把app按页面去划分,一个页面就是一个page对象 每个页面的元素集中管理.页面上按钮操作方法单独封装 # __author__ = " Caric Le ...

  4. 「LibreOJ NOI Round #2」不等关系

    「LibreOJ NOI Round #2」不等关系 解题思路 令 \(F(k)\) 为恰好有 \(k\) 个大于号不满足的答案,\(G(k)\) 表示钦点了 \(k\) 个大于号不满足,剩下随便填的 ...

  5. IntelliJ IDEA 2019 激活码 | 全产品 | 跨平台 | Goland | PhpStorm | Rider | CentOS | Windows

    >>> 下载地址: https://kenkao.pipipan.com/fs/14896800-375468824 >>> 下载地址2: https://pan. ...

  6. mybatis 多个中间表查询映射

    最近项目用到中间表,则遇到如何联查映射的问题,之前一直都是一个表头,多个明细或者一对一这样的关系,没遇到这样的问题,所以趁机找了下资料解决了这个问题. 表结构设计如下: 主表: CREATE TABL ...

  7. java之struts2之文件下载

    1.在实际应用开发中,文件下载功能也非常常见. 2.最简单的文件下载方式是通过超链接来进行文件下载: <body> <a href="download/s.txt" ...

  8. Visual Studio 2019 使用.Net Core 3.0 一

    一.前言 早在很久之前微软便公布 .NET Core 3.0 将支持开发Winform应用程序等等新特性,现如今 .NET Core 3.0 预览版已经出来第八个预览版了,从 .NET Core 2. ...

  9. 了解Django之前

      什么是web应用? 通俗地讲,就是通过浏览器访问一个网址,该网站从后台调取数据,然后把相应的界面展示给用户这样的一个过程. 什么是HTTP协议? 即超文本传输协议:规定了客户端与服务端消息传输的格 ...

  10. iOS - WebRTC的实现原理

    再简单地介绍一下webrtc: WebRTC,名称源自网页实时通信(Web Real-Time Communication)的缩写,简而言之它是一个支持网页浏览器进行实时语音对话或视频对话的技术. 它 ...