题目链接  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题,树分块 + 并查集的撤销)的更多相关文章

  1. HDU 6268 Master of Subgraph (2017 CCPC 杭州 E题,树分治 + 树上背包)

    题目链接  2017 CCPC Hangzhou  Problem E 题意  给定一棵树,每个点有一个权值,现在我们可以选一些连通的点,并且把这点选出来的点的权值相加,得到一个和. 求$[1, m] ...

  2. 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 ...

  3. [HDU6271]Master of Connected Component

    [HDU6271]Master of Connected Component 题目大意: 给出两棵\(n(n\le10000)\)个结点的以\(1\)为根的树\(T_a,T_b\),和一个拥有\(m( ...

  4. 2017 ccpc哈尔滨 A题 Palindrome

    2017 ccpc哈尔滨 A题 Palindrome 题意: 给一个串\(T\),计算存在多少子串S满足\(S[i]=S[2n−i]=S[2n+i−2](1≤i≤n)\) 思路: 很明显这里的回文串长 ...

  5. HDU 6270 Marriage (2017 CCPC 杭州赛区 G题,生成函数 + 容斥 + 分治NTT)

    题目链接  2017 CCPC Hangzhou Problem G 题意描述很清晰. 考虑每个家庭有且仅有$k$对近亲的方案数: $C(a, k) * C(b, k) * k!$ 那么如果在第$1$ ...

  6. 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 ...

  7. 2017 CCPC 杭州 流水账

    day0: 队内训练ccpc 秦皇岛,敝校自己出的题,感觉一个星期没怎么写代码,手生得很,不出意料被打飞了. day1 (热身赛): 热身赛还算顺利,A题看有的队几分钟就草过去了,还以为又是西安ICP ...

  8. 2017 CCPC秦皇岛 A题 A Ballon Robot

    The 2017 China Collegiate Programming Contest Qinhuangdao Site is coming! There will be  teams parti ...

  9. 2017 CCPC 杭州 HDU6273J 区间修改(线段树&差分数组)

    http://acm.hdu.edu.cn/downloads/CCPC2018-Hangzhou-ProblemSet.pdf 解析 线段树区间延迟更新 或 差分数组 两个数   统计2和3的最少的 ...

随机推荐

  1. 一个Objective-C对象如何进行内存布局?(考虑有父类的情况)

    1.对象isa指向类对象,类对象的isa指向元类.元类isa指向根元类.根元类的isa指针指向自己,superclass指针指向NSObject类 2.实例对象结构体只有一个isa变量,指向实例对象所 ...

  2. Jforum环境搭建

    前提:搭建好JDK.JRE.Tomcat.数据库 1.之前安装了Navicat Premium,所以直接用这个创建名为jforum的MySQL数据库,默认密码为空,记得设置密码,因为Jforum要用到 ...

  3. python 之发送邮件服务[原著] 海瑞博客

    Python 发送邮件 使用默认的django的发送邮件,只适用于单邮箱. 作者:海瑞博客 http://www.hairuinet.com/ setting中配置 # send e-mail EMA ...

  4. ZOJ 3724 Delivery 树状数组好题

    虽然看起来是求最短路,但因为条件的限制,可以转化为区间求最小值. 对于一条small path [a, b],假设它的长度是len,它对区间[a, b]的影响就是:len-( sum[b]-sum[a ...

  5. UVALive 6324 Archery (求射箭覆盖的期望)

    #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> const d ...

  6. c#中RadioButtonList选中后不整体刷新页面保持选中状态

    c#中用asp的RadioButtonList控件总会遇到选中了,然后跟着就刷新整体页面,又变为没有选中状态. <%@ Page Language="C#" AutoEven ...

  7. nf_register_hooks解读

    nf_register_hooks是什么 net->netns_nf->nf_hook_entry[NFPROTO_NUMPROTO][NF_MAX_HOOKS=8] (nf)       ...

  8. Dictionary & Chinese

    Dictionary & Chinese DC & dict https://github.com/zollero/simplified-chinese https://github. ...

  9. BZOJ3668 [Noi2014]起床困难综合症 【贪心】

    题目 21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm 一直坚持与起床困难综合症作斗争.通过研究相关文献,他找到了该病的发病原因 ...

  10. 虚拟机——vmtools安装出现Detected GCC binary at usr.bin.gcc.

    在安装VMWare Tools遇到过这样一个问题 Searching for GCC... Detected GCC binary at "/usr/bin/gcc". The p ...