个人感觉挺有意思的,然而被颜神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. JavaScript---设计模式之职责链模式

    概念 职责链模式是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止. 链中收到请求的对象要么亲自处理它,要 ...

  2. Python:TypeError: 'range' object doesn't support item deletion

    报错代码: dataIndex = range(m) del (dataIndex[randIndex]) 报错信息: 错误原因: python3 range返回的是range对象,不是数组对象 解决 ...

  3. libevent学习二(Working with an event loop)

    Runing the loop #define EVLOOP_ONCE             0x01 #define EVLOOP_NONBLOCK         0x02 #define EV ...

  4. generator-ivweb 基于react-redux的多页脚手架

    背景 每个公司甚至每个项目组,在开发新项目的时候都会有一些自己特色的东西,比如公共组件,ajax请求拦截处理,内部积累的一些业务逻辑等等,如果没有自己的脚手架,那么拷贝代码成为常态,每个项目的结构,甚 ...

  5. mysql 开启远程连接

    如图,修改mysql数据库中user表中的User字段为root的host为%,然后重新启动mysql服务即可让远程桌面连接本地.

  6. TPO-12 C1 Revise a Hemingway paper

    TPO-12 C1 Revise a Hemingway paper 第 1 段 1.Listen to a conversation between a student and a professo ...

  7. 前端开发工程师 - 03.DOM编程艺术 - 期末考试

    期末考试客观题 返回    倒计时: 01:24 1 单选(2分) 以下选项中不是节点类型的是 A. COMMENT_NODE B. DOCUMENT_NODE C. BODY_NODE D. E ...

  8. EasyUI学习心得

    因为要修改十几年前的一个项目界面,打9月份开始学习EasyUI,很多事情都要自己试过才知道,小问题会浪费很多时间.所以,就在此记录一下,随时更新. 一.引号 EasyUI的自定义关键字的识别,API文 ...

  9. adb 常用命令及操作

    获取序列号: adb get-serialno 查看连接计算机的设备: adb devices 重启机器: adb reboot 重启到bootloader,即刷机模式: adb reboot boo ...

  10. [Install] TeamViewer

    安装TeamViwer 1. $ sudo apt-get -f install 2. 使用gdebi安装TeamViwer. 所以先安装gdebi package. $ sudo apt-get i ...