4539: [Hnoi2016]树
4539: [Hnoi2016]树
分析:
主席树+倍增。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define pa pair<int,int>
using namespace std;
typedef long long LL;
#define int LL
inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ;
struct Edge { int to, nxt; } e[N << ];
struct OPT { int l, r, fa, rt; } q[N];
int head[N], dfn[N], st[N], ed[N], pos[N], fa[N][], siz[N], f[N][], g[N][], d1[N], d2[N];
set< pa > s;
int En, Index, NowIndex, n; inline void add_edge(int u,int v) {
++En; e[En].to = v, e[En].nxt = head[u]; head[u] = En;
++En; e[En].to = u, e[En].nxt = head[v]; head[v] = En;
}
struct SegmentTree{
int sum[N * ], ls[N * ], rs[N * ], Root[N], TreeIndex;
void Insert(int l,int r,int &now,int pre,int p) {
if (!now) now = ++TreeIndex;
sum[now] = sum[pre] + ;
if (l == r) return ;
int mid = (l + r) >> ;
if (p <= mid) {
rs[now] = rs[pre];
Insert(l, mid, ls[now], ls[pre], p);
} else {
ls[now] = ls[pre];
Insert(mid + , r, rs[now], rs[pre], p);
}
}
int query(int l,int r,int H,int T,int k) {
if (l == r) return l;
int mid = (l + r) >> ;
if (k <= sum[ls[T]] - sum[ls[H]]) return query(l, mid, ls[H], ls[T], k);
else return query(mid + , r, rs[H], rs[T], k - (sum[ls[T]] - sum[ls[H]]));
}
}T;
void dfs(int u) {
d1[u] = d1[fa[u][]] + ;
st[u] = ++Index; pos[Index] = u; siz[u] = ;
for (int i = ; i <= ; ++i) fa[u][i] = fa[fa[u][i - ]][i - ];
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v == fa[u][]) continue;
fa[v][] = u;
dfs(v);
siz[u] += siz[v];
}
ed[u] = Index;
}
int LCA1(int u,int v) {
if (d1[u] < d1[v]) swap(u, v);
int d = d1[u] - d1[v];
for (int i = ; ~i; --i) if ((d >> i) & ) u = fa[u][i];
if (u == v) return u;
for (int i = ; ~i; --i) if (fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
return fa[u][];
}
int getdis(int x,int y) {
return d1[x] + d1[y] - d1[LCA1(x, y)] * ;
}
void add(int id) {
int x = read(), y = read(), z;
q[id].l = NowIndex, q[id].r = (NowIndex += siz[x]) - , q[id].rt = x;
set< pa > :: iterator it = s.lower_bound(pa(y, )); z = q[it->second].rt;
q[id].fa = T.query(, n, T.Root[st[z] - ], T.Root[ed[z]], y - q[it->second].l + );
f[id][] = it->second, g[id][] = getdis(q[id].fa, z) + ;
d2[id] = d2[it->second] + ;
for (int i = ; i <= ; ++i) f[id][i] = f[f[id][i - ]][i - ], g[id][i] = g[id][i - ] + g[f[id][i - ]][i - ];
s.insert(pa(q[id].r, id));
}
int LCA2(int u,int v,int tu,int tv) {
if (d2[u] < d2[v]) swap(u, v), swap(tu, tv);
int ans = , t = u, d = d2[u] - d2[v];
for (int i = ; ~i; --i) if ((d >> i) & ) ans += g[u][i], u = f[u][i];
if (u == v) {
d --; ans = ; u = t;
for (int i = ; ~i; --i) if ((d >> i) & ) ans += g[t][i], t = f[t][i];
ans += getdis(q[t].fa, tv) + + getdis(tu, q[u].rt);
return ans;
}
ans += getdis(tu, q[t].rt) + getdis(tv, q[v].rt);
for (int i = ; ~i; --i) if (f[u][i] != f[v][i]) ans += g[u][i] + g[v][i], u = f[u][i], v = f[v][i];
ans += getdis(q[u].fa, q[v].fa) + ;
return ans;
}
void Ask() {
int u = read(), v = read(), ans, iu, iv, tu, tv;
iu = s.lower_bound(pa(u, ))->second, iv = s.lower_bound(pa(v, ))->second;
tu = T.query(, n, T.Root[st[q[iu].rt] - ], T.Root[ed[q[iu].rt]], u - q[iu].l + );
tv = T.query(, n, T.Root[st[q[iv].rt] - ], T.Root[ed[q[iv].rt]], v - q[iv].l + );
if (iu != iv) ans = LCA2(iu, iv, tu, tv);
else ans = getdis(tu, tv);
printf("%lld\n", ans);
}
signed main() {
n = read();int m = read(), Q = read();
for (int i = ; i < n; ++i) add_edge(read(), read());
dfs();
for (int i = ; i <= n; ++i)
T.Insert(, n, T.Root[i], T.Root[i - ], pos[i]);
NowIndex = n + ;
s.insert(pa(n, )); q[].l = , q[].r = n, q[].rt = , q[].fa = ;
for (int i = ; i <= m; ++i) add(i + );
while (Q --) Ask();
return ;
}
4539: [Hnoi2016]树的更多相关文章
- BZOJ 4539: [Hnoi2016]树 [主席树 lca]
4539: [Hnoi2016]树 题意:不想写.复制模板树的子树,查询两点间距离. *** 终于有一道会做的题了...... 画一画发现可以把每次复制的子树看成一个大点来建一棵树,两点的lca一定在 ...
- bzoj 4539 [Hnoi2016]树——主席树+倍增
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4539 明明就是把每次复制的一个子树当作一个点,这样能连出一个树的结构,自己竟然都没想到.思维 ...
- bzoj 4539: [Hnoi2016]树
Description 小A想做一棵很大的树,但是他手上的材料有限,只好用点小技巧了.开始,小A只有一棵结点数为N的树,结 点的编号为1,2,-,N,其中结点1为根:我们称这颗树为模板树.小A决定通过 ...
- [BZOJ4539][HNOI2016]树(主席树)
4539: [Hnoi2016]树 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 746 Solved: 292[Submit][Status][D ...
- 【LG3248】[HNOI2016]树
[LG3248][HNOI2016]树 题面 洛谷 题解 因为每次你加入的点是原树上某一棵子树 那么我们一次加入一个点,代表一棵子树加到大树下面 那么我们要找到一个点在一个大点中用主席树在\(dfs\ ...
- [HNOI2016]树(可持久化线段树+树上倍增)
[HNOI2016]树(可持久化线段树+树上倍增) 题面 给出一棵n个点的模板树和大树,根为1,初始的时候大树和模板树相同.接下来操作m次,每次从模板树里取出一棵子树,把它作为新树里节点y的儿子.操作 ...
- BZOJ4539: [Hnoi2016]树
复制的树缩点,主席树查k小,毫无技术含量,纯码农题. #include<bits/stdc++.h> #define u first #define v second #define F ...
- [HNOI2016]树
Description 小A想做一棵很大的树,但是他手上的材料有限,只好用点小技巧了.开始,小A只有一棵结点数为N的树,结 点的编号为1,2,…,N,其中结点1为根:我们称这颗树为模板树.小A决定通过 ...
- 2019.03.25 bzoj4539: [Hnoi2016]树(主席树+倍增)
传送门 题意:给一棵大树,令一棵模板树与这棵树相同,然后进行mmm次操作,每次选择模板树中的一个节点aaa和大树中一个节点bbb,把aaa这棵子树接在bbb上面,节点编号顺序跟aaa中的编号顺序相同. ...
随机推荐
- 使用Instruments中的CoreAnimation分析动画
使用Instruments中的CoreAnimation分析动画 1. 打开Instruments中的CoreAnimation 2. 运行前的准备工作 要注意勾选以下选项,便于调试 3. 运行与调试 ...
- 详细讲解WaterRefreshLoadMoreView的使用
详细讲解WaterRefreshLoadMoreView的使用 效果图: 加载控件的源码在如下网址中:上拉加载下拉刷新控件WaterRefreshLoadMoreView 使用的源码: // // V ...
- 安装oracle 11g时,报启动服务出现错误,找不到OracleMTSRecoveryService的解决方法
很多人在安装orcl数据库时,出现很多报错,我也不例外,因上次数据库出现问题,无法修复,只能从新安装,无奈的是,安装时报启动服务出现错误,找不到OracleMTSRecoveryService错MMP ...
- Linux系统优化实现高并发
ulimit -SHn 65535内核优化net.ipv4.ip_forward = 1 #开启路由功能net.ipv4.conf.default.rp_filter = 1 ...
- win10不错的快捷键
A I S number 左右 上下 , Win键 Open Action center. Open Settings. Open Search. Open the app pinned to t ...
- 最新版本2018.1.1webstorm安装、汉化、破解教程
一.安装(下载与激活) 1.官网下载安装包https://www.jetbrains.com/webstorm/ 2.开始安装 3.选择安装目录,点击下一步 4.勾选64位,点击下一步 5.继续下一步 ...
- 【python库安装问题解决】UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc0 in position 121: invalid start byte
好久没用python了...今天随便pip安装个库突然报错: Exception:‘’ (most recent call last): File "C:\ProgramData\Anac ...
- P4906 小奔关闹钟
题目背景 由于今天是星期一,闹钟准时响了,由于小奔太困了,所以她想关停闹钟. 题目描述 可是,他的闹钟电路太复杂了,有很多个开关,每个开关都连着其他开关,其他开关又连着更多的开关,当且仅当所有开关都关 ...
- Day5 JDBC
JDBC的简介 Java Database Connectivity:连接数据库技术. SUN公司为了简化.统一对数据库的操作,定义了一套Java操作数据库的规范(接口),使用同一套程序操作不同的数 ...
- Windows10中以管理员身份打开命令提示符
WIN+X+A (要关闭替换) 从任务栏启动 从开始菜单 从资源管理器 连贯即(alt+f+s+a)