HDU 6271 Master of Connected Component(2017 CCPC 杭州 H题,树分块 + 并查集的撤销)
题目链接 2017 CCPC Hangzhou Problem H
思路:对树进行分块。把第一棵树分成$\sqrt{n}$块,第二棵树也分成$\sqrt{n}$块。
分块的时候满足每个块是一个连通块,那么每个块就有一个共同的祖先。
把询问按照第一个点被第一棵树的哪个祖先管辖和第二个点被第二棵树的哪个祖先管辖,分成$n$类。
每一类询问一起处理,处理完后用可撤销并查集恢复到之前的状态。
每一类询问之间依次转移,每次转移,移动次数不会超过$\sqrt{n}$次。
最后总时间复杂度$O(n^{1.5}logn)$
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <unordered_map> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second typedef long long LL; const int N = 1e4 + 10;
const int M = 505; struct node{
int x, y, id;
} s[N << 5]; int T;
int n, m;
int top;
int fa1[N], fa2[N], bs;
int id1[N], id2[N];
int re[M][M];
int father[N], sz[N];
int ans;
int ret[N];
int ux[N], uy[N], vx[N], vy[N]; vector <int> v[N], v1, v2;
vector <node> q[M][M]; void dfs1(int x, int fa, int dep){
fa1[x] = fa;
id1[x] = -1;
if (dep % bs == 0){
id1[x] = v1.size();
v1.push_back(x);
} for (auto u : v[x]){
if (u == fa) continue;
dfs1(u, x, dep + 1);
}
} void dfs2(int x, int fa, int dep){
fa2[x] = fa;
id2[x] = -1; if (dep % bs == 0){
id2[x] = v2.size();
v2.push_back(x);
} for (auto u : v[x]){
if (u == fa) continue;
dfs2(u, x, dep + 1);
}
} void merge_(int x, int y){
while (x != father[x]) x = father[x];
while (y != father[y]) y = father[y]; if (x == y) return; if (sz[x] > sz[y]) swap(x, y); s[++top] = {x, y};
father[x] = y; --ans;
sz[y] += sz[x];
} void recover(int x, int y){
while (top > re[id1[x]][id2[y]]){
auto u = s[top--];
++ans;
father[u.x] = u.x;
father[u.y] = u.y;
sz[u.y] -= sz[u.x];
}
} void commit(int x, int y){
int tx = x, ty = y;
for (; id1[tx] == -1; tx = fa1[tx]){}
for (; id2[ty] == -1; ty = fa2[ty]){} recover(tx, ty); while (x != tx){
merge_(ux[x], vx[x]);
x = fa1[x];
} while (y != ty){
merge_(uy[y], vy[y]);
y = fa2[y];
}
} int main(){ scanf("%d", &T);
while (T--){
scanf("%d%d", &n, &m);
rep(i, 1, n) scanf("%d%d", ux + i, vx + i); bs = sqrt(n); rep(i, 0, n + 1) v[i].clear(); rep(i, 2, n){
int x, y;
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
} v1.clear();
dfs1(1, 0, 0); rep(i, 0, n + 1) v[i].clear();
rep(i, 1, n) scanf("%d%d", uy + i, vy + i); rep(i, 2, n){
int x, y;
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
} v2.clear();
dfs2(1, 0, 0); rep(i, 1, n){
int u, v, x, y;
u = v = i;
x = u, y = v; for (; id1[x] == -1; x = fa1[x]){}
for (; id2[y] == -1; y = fa2[y]){} q[id1[x]][id2[y]].push_back({u, v, i}); } rep(i, 1, m) father[i] = i, sz[i] = 1; ans = m; merge_(ux[1], vx[1]);
merge_(uy[1], vy[1]); re[0][0] = (top = 0); for (auto x : v1){
for (auto y : v2){
if (x == 1 && y == 1){
merge_(ux[x], vx[x]);
merge_(uy[y], vy[y]);
} else if (y == 1){
commit(fa1[x], y);
merge_(ux[x], vx[x]);
} else{
commit(x, fa2[y]);
merge_(uy[y], vy[y]);
} re[id1[x]][id2[y]] = top; for (auto u : q[id1[x]][id2[y]]){
commit(u.x, u.y);
ret[u.id] = ans;
} q[id1[x]][id2[y]].clear();
}
} rep(i, 1, n) printf("%d\n", ret[i]); } return 0;
}
HDU 6271 Master of Connected Component(2017 CCPC 杭州 H题,树分块 + 并查集的撤销)的更多相关文章
- HDU 6268 Master of Subgraph (2017 CCPC 杭州 E题,树分治 + 树上背包)
题目链接 2017 CCPC Hangzhou Problem E 题意 给定一棵树,每个点有一个权值,现在我们可以选一些连通的点,并且把这点选出来的点的权值相加,得到一个和. 求$[1, m] ...
- 2017 CCPC秦皇岛 H题 Prime set
Given an array of integers , we say a set is a prime set of the given array, if and is prime. Ba ...
- [HDU6271]Master of Connected Component
[HDU6271]Master of Connected Component 题目大意: 给出两棵\(n(n\le10000)\)个结点的以\(1\)为根的树\(T_a,T_b\),和一个拥有\(m( ...
- 2017 ccpc哈尔滨 A题 Palindrome
2017 ccpc哈尔滨 A题 Palindrome 题意: 给一个串\(T\),计算存在多少子串S满足\(S[i]=S[2n−i]=S[2n+i−2](1≤i≤n)\) 思路: 很明显这里的回文串长 ...
- HDU 6270 Marriage (2017 CCPC 杭州赛区 G题,生成函数 + 容斥 + 分治NTT)
题目链接 2017 CCPC Hangzhou Problem G 题意描述很清晰. 考虑每个家庭有且仅有$k$对近亲的方案数: $C(a, k) * C(b, k) * k!$ 那么如果在第$1$ ...
- Valentine's Day Round hdu 5176 The Experience of Love [好题 带权并查集 unsigned long long]
传送门 The Experience of Love Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Ja ...
- 2017 CCPC 杭州 流水账
day0: 队内训练ccpc 秦皇岛,敝校自己出的题,感觉一个星期没怎么写代码,手生得很,不出意料被打飞了. day1 (热身赛): 热身赛还算顺利,A题看有的队几分钟就草过去了,还以为又是西安ICP ...
- 2017 CCPC秦皇岛 A题 A Ballon Robot
The 2017 China Collegiate Programming Contest Qinhuangdao Site is coming! There will be teams parti ...
- 2017 CCPC 杭州 HDU6273J 区间修改(线段树&差分数组)
http://acm.hdu.edu.cn/downloads/CCPC2018-Hangzhou-ProblemSet.pdf 解析 线段树区间延迟更新 或 差分数组 两个数 统计2和3的最少的 ...
随机推荐
- Nuget.config格式错误,请检查nuget.config配置文件
安装 VS 2015 Professional 版,安装后,我想加一个nuget的包配置. 然后提示我:Nuget.config格式错误,请检查nuget.config配置文件 我找到了 Nuget. ...
- MySQL高可用之MHA安装
Preface MasterHA is a tool which can be used in MySQL HA architecture.I'm gonna implement it ...
- PICT:基于正交法的软件测试用例生成工具
成对组合覆盖这一概念是Mandl于1985年在测试Aad编译程序时提出来的.Cohen等人应用成对组合覆盖测试技术对Unix中的“Sort”命令进行了测试.测试结果表明覆盖率高达90%以上.可见成对组 ...
- eclipse importing maven projects 卡顿
导入一个maven工程后 一直显示 importing maven projects 9% 解决办法: 找到eclipse安装目录下的eclipse.ini 在最后加入 -vm $JAVA_HOME% ...
- (原)Unreal渲染模块 管线 - 着色器(1)
@author: 白袍小道 转载悄悄说明下 随缘查看,施主开心就好 说明: 本篇继续Unreal搬山部分的渲染模块的Shader部分, 主要牵扯模块RenderCore, ShaderCore, RH ...
- 洛谷P1071潜伏者(提高组)
题目描述 R国和S国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动.历尽艰险后,潜伏于S国的R 国间谍小C终于摸清了 S 国军用密码的编码规则: 1. S国军方内部欲发送的原信息经过加密后在网 ...
- 在Struts2 Action中快速简便的访问Request、Session等变量
前言——正常情况下如何在Action中获取到这些变量 全部方法(共四种)可以参考:http://blog.csdn.net/itmyhome1990/article/details/7019476 这 ...
- 【linxu】部署docker容器虚拟化平台
实验所涉内容 Docker 概述 部署 docker 容器虚拟化平台 docker 平台基本使用方法 创建docker镜像和发布镜像方法 Container 容器端口映射 一 Docker 概述 Do ...
- 201621123034 《Java程序设计》第7周学习总结
作业07-Java GUI编程 1. 本周学习总结 1.1 思维导图:Java图形界面总结 1.2 可选:使用常规方法总结其他上课内容. 2.书面作业 1. GUI中的事件处理 1.1 写出事件处理模 ...
- vue.$refs 的用法
官网给出的解释是: 被用来给元素或子组件注册引用信息.引用信息将会注册在父组件的 $refs 对象上. 1.如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素; 2.如果用在子组件上,引用 ...