个人感觉挺有意思的,然而被颜神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. iOS应用App Store发布流程

    iOS应用App Store发布流程 要发布iOS应用到App Store首先得有一个开发者账号,且不能是企业版(企业版只能部署inhouse,不能部署到App Store). 应用发布到App St ...

  2. elasticsearch增删改查操作

    目录 1. 插入数据 2. 更改数据 3. 删除数据 4. 检索文档 1. 插入数据 关于下面的代码如何使用,可以借助于kibana的console,浏览器打开地址: http://xxx.xxx.x ...

  3. “地表最贵iPhone”到货,iPhone XS 系列手机等你来测!

    WeTest 导读 9月13日,苹果正式发布了全新的 iPhone XS 系列智能手机,备受瞩目的iPhone家族新成员具体又是怎样的呢?   关于iPhone XS系列手机的那些新亮点   大屏.双 ...

  4. centos下testlink的部署(基于xampp)

    1. sudu -i 切换root用户      cd /opt切换到opt目录下(在linux下默认的下载文件目录在opt下) 执行命令下载xampp:      https://sourcefor ...

  5. [CodeForce721C]Journey

    题目描述 Recently Irina arrived to one of the most famous cities of Berland - the Berlatov city. There a ...

  6. vmware centOS上网配置笔记

    ⦁    修改/etc/sysconfig/network-scripts/ifcfg-eth0文件  (首先查看本机vmware 虚拟网络编辑器中的网关) 重启网络 使用命令:service net ...

  7. 使用DataTables导出html表格

    去年与同事一起做一个小任务,需要把HTML表格中的数据导出到Excel.用原生js想要实现,只有IE浏览器提供导出到微软的Excel的接口,这就要求你电脑上必须安装IE浏览器.Excel,而且必须修改 ...

  8. Bower 显示‘bower ESUDO Cannot be run with sudo’的错误解决方法

    使用 sudo 命令后或者当前用户为 root,执行 bower 相关命令会出现错误: 解决办法: 在命令后面加 --allow-root 例: bower init  --allow-root bo ...

  9. C中的除法,商和余数的大小、符号如何确定

    对于C中的除法,商和余数的大小.符号是如何确定的呢?在C89中,只规定了如果两个数为正整数,那么余数的符号为正,并且商的值是接近真实值的最大整数.比如5 / 2,那么商就是2,余数就是1.但是,C89 ...

  10. 衡量失业:失业率(Unemployment Rate)

    定义 劳动力 = 就业人数 + 失业人数 失业率 = (失业人数 / 劳动力) * % 劳动力参与率 = (劳动力 / 成年人口) * %