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的最少的 ...
随机推荐
- SQL 与关系代数
Table of Contents 前言 关系与表 关系代数的基本运算 投影 选择 并运算 集合差运算 笛卡尔积 更名运算 关系代数的附加运算 集合交运算 连接运算 自然连接 内连接 外连接 结语 前 ...
- python 学习分享-线程
多线程类似于同时执行多个不同程序,多线程运行有如下优点: 使用线程可以把占据长时间的程序中的任务放到后台去处理. 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进 ...
- input()报错:TypeError: '>=' not supported between instances of 'str' and 'int'
今天学习python基础—分支与循环,接触到了if.在练习一个if语句的时候,出现了错误. 题目是: 根据分数划分成四个级别:优秀.良好.及格.不及格,分数是72: grade = 72if grad ...
- ES6常用片段
promise: --在return里面: methods:{ getSellData(){ return axios.get('/api/seller').then((res=>{ retur ...
- 孤荷凌寒自学python第三十二天python的代码块中的异常的捕获
孤荷凌寒自学python第三十二天python的代码块中的异常的捕获 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天简单了解了Python的错误陷阱,了解到其与过去学过的其它语言非常类似 ...
- packstack测试环境安装heat
虚机all in one环境测试安装heat [root@armstrong ~]# tmux at -t mysql MariaDB [(none)]> CREATE DATABASE hea ...
- 爬虫:Scrapy8 - Item Pipeline
当 Item 在 Spider 中被收集之后,它将会被传递到 Item Pipeline,一些组件会按照一定的顺序执行对 Item 的处理. 每个 item pipeline 组件(有时也称之为“It ...
- beta版本前准备
目录 过去存在的问题 任务分工 开发规范 后端总结 卉卉 家灿 前端总结 绪佩 青元 恺琳 宇恒 丹丹 算法&API接口 家伟 鸿杰 一好 文档&博客撰写 政演 产品功能 我们已经做了 ...
- java 中基本类型与字符串之间的互相转换
1. 由 基本数据型态转换成 String String 类别中已经提供了将基本数据型态转换成 String 的 static 方法 也就是 String.valueOf() 这个参数多载的方法 有下 ...
- nagios服务端安装
系统环境:操作系统:CentOS-5.7 x86_64Apache版本: Apache-2.2.22Nagios版本: nagios-3.3.1GD库: gd-2.0.33 2.安装前准备:2.1.安 ...