CF855G. Harry Vs Voldemort

Solution

考虑每增加一条边都会把路径上的边双都连成一个大边双,考虑合并xxx和y=faxy = fa_xy=fax​ 这两个边双的贡献,分类讨论:

  1. 选取三个同边双内的点。
  2. 选取在同一个边双内选两个点,剩下一个在其他边双内。
  3. 选取三个来自不同边双的点。

第一个的贡献即为Aszx3A_{sz_x}^3Aszx​3​
第二个的贡献即为2Aszx2(n−szx)2A_{sz_x}^2(n - sz_x)2Aszx​2​(n−szx​)
第三个比较麻烦:

  • 首先我们去掉在一二两种中重复的部分,这部分可能是(x,y,z)(x,y,z)(x,y,z),(y,x,z)(y,x,z)(y,x,z),(z,x,y)(z,x,y)(z,x,y),(z,y,x)(z,y,x)(z,y,x)。
  • 然后我们发现合并(x,y)(x,y)(x,y)之后,就可以从本来xxx子树中的点ppp开始走到yyy再回走到xxx的另一个子树中的点qqq,即(p,y,q)(p,y,q)(p,y,q)和(q,y,p)(q,y,p)(q,y,p)都可以选择,这一部分是新多出来的,这部分相当于xxx的不同子树内的点对两两可达,于是我们再维护一个hx=∑yszy2h_x = \sum_{y}sz_y^2hx​=∑y​szy2​即可快速统计贡献。(对于yyy这一部分的贡献同理)

具体统计方法见CodeCodeCode。

并查集维护边双联通分量即可,时间复杂度O(nlgn)O(nlgn)O(nlgn)。

Code

#include <bits/stdc++.h>using namespace std;template<typename T> inline bool upmin(T &x, T y) { return y < x ? x = y, 1 : 0; }
template<typename T> inline bool upmax(T &x, T y) { return x < y ? x = y, 1 : 0; }#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se second
#define int lltypedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int, int> PR;
typedef vector<int> VI; const lod eps = 1e-11;
const lod pi = acos(-1);
const int mods = 998244353;
const int oo = 1 << 30;
const ll loo = 1ll << 62;
const int MAXN = 600005;
const int INF = 0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read() {int f = 1, x = 0; char c = getchar();while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }while (c >= '0' && c <= '9') { x = (x << 3) + (x << 1) + (c ^ 48); c = getchar(); }return x * f;
}
vector<int> e[MAXN];
int fa[MAXN], f[MAXN], dep[MAXN];
ll sz[MAXN], num[MAXN], g[MAXN], h[MAXN], ans = 0, n;
int find(int x) { return f[x] == x ? f[x] : f[x] = find(f[x]); }
void dfs(int x, int father) {sz[x] = 0, fa[x] = father, dep[x] = dep[father] + 1;for (auto v : e[x]) if (v != father) dfs(v, x);for (auto v : e[x]) {if (v == father) continue;ans += sz[x] * sz[v] * 2;g[x] += g[v] + sz[v];h[x] += sz[v] * sz[v];sz[x] += sz[v]; }++ sz[x];h[x] += (n - sz[x]) * (n - sz[x]);ans += (n - sz[x]) * (sz[x] - 1) * 2;
}
void merge(int x, int y) {ans -= num[x] * (num[x] - 1) * (num[x] - 2); //part 1 xans -= num[y] * (num[y] - 1) * (num[y] - 2); //part 1 yans -= num[x] * (num[x] - 1) * (n - num[x]) * 2; //part 2 xans -= num[y] * (num[y] - 1) * (n - num[y]) * 2; //part 2 yans -= (sz[x] - num[x]) * num[x] * num[y] * 2 + (n - sz[x] - num[y]) * num[x] * num[y] * 2; //part 3.1ans += num[y] * ((sz[x] - num[x]) * (sz[x] - num[x]) - (h[x] - (n - sz[x]) * (n - sz[x]))); //part 3.2 xans += num[x] * ((n - sz[x] - num[y]) * (n - sz[x] - num[y]) - (h[y] - sz[x] * sz[x])); //part 3.2 yf[x] = y, num[y] += num[x], h[y] += h[x] - sz[x] * sz[x] - (n - sz[x]) * (n - sz[x]);ans += num[y] * (num[y] - 1) * (num[y] - 2); //part 1 new ans += num[y] * (num[y] - 1) * (n - num[y]) * 2; //part 2 new
}
signed main() {n = read();for (int i = 1, u, v; i < n ; ++ i) u = read(), v = read(), e[u].PB(v), e[v].PB(u);for (int i = 1; i <= n ; ++ i) f[i] = i, num[i] = 1;dfs(1, 0);printf("%lld\n", ans);int Case = read();while (Case --) {int u = read(), v = read(), U = find(u), V = find(v);while (U != V) {if (dep[U] < dep[V]) swap(U, V);merge(U, find(fa[U]));U = find(U);}  printf("%lld\n", ans);}return 0;
}

CF855G. Harry Vs Voldemort(边双,并查集,dp)相关推荐

  1. POJ 1417 True Liars(路径压缩并查集+DP背包问题)

    POJ 1417 True Liars(路径压缩并查集+DP背包问题) http://poj.org/problem?id=1417 题意: 给出p1+p2个人,其中p1个是好人,p2个是坏人.然后有 ...

  2. P1455-搭配购买【图论,并查集,dp,背包】

    正题 题目链接: https://www.luogu.org/problemnew/show/P1455 大意 有n个商品,给出价值和价格.有m组搭配,如果买了其中一个就得买另一个,给出你拥有的钱,求 ...

  3. 【并查集+dp】Team

    Team 时间限制: 1 Sec  内存限制: 128 MB 提交: 124  解决: 10 [提交] [状态] [命题人:admin] 题目描述 ACM-ICPC is a interesting ...

  4. POJ 1417 True Liars(带权并查集+DP)

    传送门 Description After having drifted about in a small boat for a couple of days, Akira Crusoe Maeda ...

  5. POJ 1417 True Liars (种类并查集+DP)

    题目:True Liars 题目大意:给出n对关系,p1个好人,p2个坏人.要求根据n对关系中找出好人有哪些,若方案唯一,则逐个输出好人,最后输出end:若方案不唯一/找不到,那么输出no 结论:通过 ...

  6. [Tarjan][并查集][dp] Jzoj P4253 QYQ在艾泽拉斯

    Description 在艾泽拉斯的无尽之海里,有着一群不为人知的由各个种族的冒险者统治的岛屿,这些岛屿都很庞大,足以在上面建造许多的城市,城市之间有一些单向道路连接. 有一天,QYQ无意中发现了这些 ...

  7. POJ 并查集 题目汇总 ——czyuan原创(转)

    继续数据结构的复习,本次的专题是:并查集. 并查集,顾名思义,干的就是"并"和"查"两件事.很多与集合相关的操作都可以用并查集高效的解决. 两个操作代码:    ...

  8. All men are brothers(并查集+思维 好题!!!)

    链接:https://ac.nowcoder.com/acm/contest/889/E 来源:牛客网 Amy asks Mr. B problem E. Please help Mr. B to s ...

  9. 【转】并查集MST题集

    转自:http://blog.csdn.net/shahdza/article/details/7779230 [HDU] 1213 How Many Tables 基础并查集★ 1272 小希的迷宫 ...

  10. [kuangbin带你飞]专题五 并查集 题解+总结

    kuangbin带你飞:点击进入新世界 总结: 本人算是初学者中的初学者,欢迎交流~ 并查集的接触过的不多,大概只有普通并查集,带权并查集,种族并查集,传说中的可持续化并查集只是听说过还没有接触,不过 ...

最新文章

  1. 线程、线程匿名内部类、解决线程不安全的方式
  2. RobotFrameWork(五)控制流之if语句——Run Keyword If
  3. java中class_JAVA中的Class类
  4. 威海二职工业机器人专业_工业机器人专业就业前景-山东省好的中专学校
  5. BZOJ 1613: [Usaco2007 Jan]Running贝茜的晨练计划
  6. Django中模型类 属性-学习笔记
  7. 二维码图像去噪文献调研(1)--Real Image Denoising with Feature Attention
  8. c++rpg黑框游戏_c++实现简单RPG对战游戏的代码
  9. Spring Cloud——服务发现与注册
  10. ES+Redis+MySQL,这个高可用架构设计太顶了!
  11. android 音频播放插件,在android中的listview中实现音频播放器
  12. MacBook M1 虚拟机安装Windows7 Xp
  13. Sentaurus入门(3):sde
  14. ps 条件动作添加 图层锁定和解锁
  15. 读《洞穴奇案》——一个人是否应该为了避免偷窃面包而挨饿致死?
  16. appcan外部网页css,Appcan开发之页面布局与CSS排版
  17. h5py 必知--String存储
  18. Nginx安装成windows server 2016机器的服务
  19. icinga用NSCA监控远程Linux服务器
  20. 海明码检错与纠错,经典例子讲解~

热门文章

  1. 习惯的力量在于不由主——知道顶个球用,成为习惯才是你的
  2. ping的通百度但是浏览器打不开的解决方法
  3. LeetCode——线段树
  4. BOMAPI和DOMAPI
  5. 【个人网站】个人网站搭建预备工作
  6. python转cython_10分钟带你入门Cython
  7. 关键词提取:TF-IDF和n-gram
  8. raptor算法流程图例题_【实验4】熟悉可视化算法描述软件(RAPTOR)使用及结构化程序设计...
  9. 由于这台计算机上储存的远程桌面,“由于这台计算机没有远程桌面客户端访问许可证,远程会话被中断”的解决方案...
  10. 我对锤子ROM 功能的看法——功能篇