个人感觉挺有意思的,然而被颜神D无聊惹(~ ̄▽ ̄)~

  这题我们可以首先试图去统计以每一个点作为 w 点所能对答案造成的贡献是多少。不难发现,当且仅当 u 和 v 都在 w 所在边双的一侧的时候不能构成一个合法的三元组,因为它们要到达 w 均需经过一条共同的割边。那么因为原图是一棵树,所以我们连接两个点的时候就是在把这两个点所在的边双一直到根所在的边双都合并为一个。

  考虑如何在合并答案的时候计算出答案的变化。若我们合并的是 S,T 这两个集合,我们可以先减去由 S 和 T 中的点作为 w 点时对答案造成的贡献。1.u 和 v 均为 w 所在边双中的点,这个直接用边双大小统计就可以了;2.一个在边双外部,一个在边双内部。这个也可以直接用边双大小进行统计。

  比较难想到的是如何统计两个点都在边双外部的情况(在边双的两侧)。这个直接统计并不是很方便,但是不难发现如果统计在点双外部且在两侧的情况是很多的,而在点双外部且在同一侧的情况则单一很多。全部的选择就是点双外部的点钟随便选两个,我们可以把在同一侧的情况减去得到合法的解。维护数组 w[u] 表示 u 联通块中的一个点所能匹配到的同一侧的两个点有多少种方案。非法的情况即为 w[u] * s[u] (u 联通块的大小)。合并的时候 w 数组怎么合并呢?令 u 为 v 的父亲,则 w[u] + w[v] 这样统计的话会把 v 所在的子树内的点对 & v 点外部(父亲子树)的点对统计两次。减去就好啦。

#include <bits/stdc++.h>
using namespace std;
#define maxn 1000000
#define int long long
int n, ans, s[maxn], w[maxn], dep[maxn];
int size[maxn], fa[maxn], f[maxn]; int read()
{
int x = , k = ;
char c; c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} struct edge
{
int cnp, to[maxn], last[maxn], head[maxn];
edge() { cnp = ; }
void add(int u, int v)
{
to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++;
}
}E1; void dfs(int u)
{
size[u] = ; dep[u] = dep[fa[u]] + ;
for(int i = E1.head[u]; i; i = E1.last[i])
{
int v = E1.to[i];
if(v == fa[u]) continue;
fa[v] = u; dfs(v);
size[u] += size[v]; w[u] += size[v] * size[v];
}
w[u] += (n - size[u]) * (n - size[u]);
ans -= w[u];
} int Cal(int u) { return max(s[u] * (s[u] - ) * (s[u] - ), 0LL); }
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
void merge(int u, int v)
{
ans -= (n - s[u]) * (n - s[u]) * s[u] - w[u] * s[u];
ans -= (n - s[v]) * (n - s[v]) * s[v] - w[v] * s[v];
ans -= (n - s[u]) * s[u] * (s[u] - ) * ;
ans -= (n - s[v]) * s[v] * (s[v] - ) * ;
ans -= Cal(u) + Cal(v); f[v] = u, s[u] += s[v]; w[u] += w[v] - size[v] * size[v] - (n - size[v]) * (n - size[v]);
ans += (n - s[u]) * (n - s[u]) * s[u] - w[u] * s[u] + Cal(u);
ans += (n - s[u]) * s[u] * (s[u] - ) * ;
} signed main()
{
n = read();
for(int i = ; i < n; i ++)
{
int u = read(), v = read();
E1.add(u, v);
}
ans = n * (n - ) * (n - ); dfs();
for(int i = ; i <= n; i ++) f[i] = i, s[i] = ;
int q = read();
printf("%lld\n", ans);
for(int i = ; i <= q; i ++)
{
int u = read(), v = read();
u = find(u), v = find(v);
while(u != v)
{
if(dep[u] < dep[v]) swap(u, v);
int fu = find(fa[u]);
merge(fu, u); u = fu;
}
printf("%lld\n", ans);
}
return ;
}

【题解】CF#855 G-Harry Vs Voldemort的更多相关文章

  1. [题解向] CF#Global Round 1の题解(A $\to$ G)

    这里是总链接\(Link\). \(A\) 题意:求\(\sum_{i=1}^{k} a_i\times b^{k-i}\)的奇偶性, \(k = \Theta(n \log n)\) --其实很容易 ...

  2. 竞赛题解 - CF Round #524 Div.2

    CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...

  3. 题解 CF 1372 B

    题目 传送门 题意 给出 \(n\),输出 \(a\) ,\(b\) (\(0 < a \leq b < n\)),使\(a+b=n\)且 \(\operatorname{lcm}(a,b ...

  4. 题解——CF Manthan, Codefest 18 (rated, Div. 1 + Div. 2) T5(思维)

    还是dfs? 好像自己写的有锅 过不去 看了题解修改了才过qwq #include <cstdio> #include <algorithm> #include <cst ...

  5. CF 1051 G. Distinctification

    G. Distinctification 链接 分析: 线段树合并 + 并查集. 最后操作完后a连续递增的一段,b一定是递减的.最后的答案是$\sum (a_{new}-a_{odd}) \times ...

  6. CF 724 G. Xor-matic Number of the Graph

    G. Xor-matic Number of the Graph 链接 题意: 给定一个无向图,一个interesting的三元环(u,v,s)满足,从u到v的路径上的异或和等于s,三元环的权值为s, ...

  7. CF 1093 G. Multidimensional Queries

    G. Multidimensional Queries 链接 分析: 考虑如何去掉绝对值符号. $\sum \limits_{i = 1}^{k} |a_{x, i} - a_{y, i}|$,由于k ...

  8. 【codeforces】【比赛题解】#855 Codefest 17

    神秘比赛,以<哈利波特>为主题……有点难. C题我熬夜切终于是写出来了,可惜比赛结束了,气啊. 比赛链接:点我. [A]汤姆·里德尔的日记 题意: 哈利波特正在摧毁神秘人的分灵体(魂器). ...

  9. 竞赛题解 - [CF 1080D]Olya and magical square

    Olya and magical square - 竞赛题解 借鉴了一下神犇tly的博客QwQ(还是打一下广告) 终于弄懂了 Codeforces 传送门 『题目』(直接上翻译了) 给一个边长为 \( ...

随机推荐

  1. Android stado 运行项目,apk does not exist on disk.

    报错如下: 03/12 21:38:56: Launching iReader The APK file F:\git\iReader_nubia\iReader\build\outputs\apk\ ...

  2. possible new indexes 出现了

  3. 生鲜水果商城PC手机微信完整版源码2018版(免费)

    采用php+mysql架构,含有PC.手机.微信三端,只需要修改一下数据库配置,并恢复一下数据即可使用,还有微信.支付宝等接口,如有问题请在文章下面留言一下,我看到会协助一下的,下载包里面含有详细的安 ...

  4. Oracle 字段拆分替换在合并成一条

    看了网上很多Oracle字段拆分的实例,但是都未能完全满足要求,或许是我水平不够未能很好的理解,如果有大神懂得并且愿意告知我的,可以私信我,在这里真诚的感谢! 1. 首先建立表并插入测试数据 drop ...

  5. Kotlin对象:仅一行代码就可创建安全的单例

    作者:Antonio Leiva 时间:Jun 20, 2017 原文链接:https://antonioleiva.com/objects-kotlin/ Kotlin对象是Android开发人员不 ...

  6. 【转】上线游戏参考数值(Unity)

    转自游戏开发主席 贴图格式: iOS :RGBA 32 (pvrtc 4 ) Android : RGB Compresed ETC 4 或 RGBA 32  . DrawCall: 总计Drawca ...

  7. [转载]启动tomcat时,一直卡在Deploying web application directory这块的解决方案

    转载:https://www.cnblogs.com/mycifeng/p/6972446.html 本来今天正常往服务器上扔一个tomcat 部署一个项目的, 最后再启动tomcat 的时候 发现项 ...

  8. 如何在线测试Exchange的速度

    最新碰到了客户需要比较国内版和国际版的Office365的速度问题,微软提供在线工具测试 这里以Exchange 测试为例子,请参考. PS Onenote贴过来只能至图片,各位看官只能将就了 这里有

  9. Python3 Tkinter-PaneWindow

    1.向PanedWindow中添加Pane from tkinter import * root=Tk() panes=PanedWindow(orient=VERTICAL) panes.pack( ...

  10. Python3 迭代器,生成器,装饰器

    1.迭代器 迭代器有两个基本方法,iter()和next(),next()完成后会引发StopIteration异常 a='abcdef' b=iter(a) #创建迭代器对象 print(type( ...