洛谷P3248 [HNOI2016]树(主席树 倍增 )
题意
Sol
从上午九点淦到现在qwq
思路比较简单,就是把每次加入的一坨点看成一个,然后直接倍增搞。。
然后慢慢调就可以了。。。
最后数量级会到达\(10^{10}\),所以应该开long long
#include<bits/stdc++.h>
#define Pair pair<LL, LL>
#define MP make_pair
#define fi first
#define se second
#define LL long long
#define int long long
using namespace std;
const int MAXN = 1e5 + 10, B = 17, SS = 7e6 + 10;
inline LL read() {
char c = getchar(); LL x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N, M, Q;
vector<int> v[MAXN];
int siz[MAXN], top[MAXN], son[MAXN], fa[MAXN], ID[MAXN], rev[MAXN], tim;
LL dep[MAXN];
void dfs1(int x, int _fa) {
siz[x] = 1; dep[x] = dep[_fa] + 1; fa[x] = _fa;
ID[x] = ++tim; rev[tim] = x;
for(auto &to : v[x]) {
if(to == _fa) continue;
dfs1(to, x);
siz[x] += siz[to];
if(siz[to] > siz[son[x]]) son[x] = to;
}
}
void dfs2(int x, int topf) {
top[x] = topf;
if(!son[x]) return ;
dfs2(son[x], topf);
for(auto &to : v[x]) {
if(top[to]) continue;
dfs2(to, to);
}
}
int LCA(int x, int y) {
while(top[x] ^ top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
if(dep[x] < dep[y]) swap(x, y);
return y;
}
LL GetDis(int x, int y) {
int lca = LCA(x, y);
return dep[x] + dep[y] - 2 * dep[lca];
}
int tot;
struct Ope {
int l, r, id, fa, ti;//id所在的根节点是哪个,fa连到了大树哪个节点下面 ti第几次操作
bool operator < (const Ope &rhs) const {
return r < rhs.r;
}
}md[MAXN];
set<Ope> lin;
int root[SS], si[SS], ls[SS], rs[SS], cnt;
void insert(int &k, int pre, int l, int r, int v) {
k = ++cnt; ls[k] = ls[pre]; rs[k] = rs[pre]; si[k] = si[pre] + 1;
if(l == r) return;
int mid = (l + r) >> 1;
if(v <= mid) insert(ls[k], ls[pre], l, mid, v);
else insert(rs[k], rs[pre], mid + 1, r, v);
}
int Query(int tl, int tr, int l, int r, int k) {
if(l == r) return l;
int cur = si[ls[tr]] - si[ls[tl]], mid = (l + r) >> 1;
if(cur >= k) return Query(ls[tl], ls[tr], l, mid, k);
else return Query(rs[tl], rs[tr], mid + 1, r, k - cur);
}
int Kth(int x, int k) {//以x节点为根的子树中第k小的节点
int l = ID[x], r = ID[x] + siz[x] - 1;
int tmp = Query(root[l - 1], root[r], 1, N, k);
//printf("%d %d %d\n", x, k, tmp);
return tmp;
}
Pair GetId(int x) {//大树中编号为x节点对应的小树中的节点编号,以及该节点被加入的时间
Ope nl = *lin.lower_bound((Ope){0, x, 0, 0, 0});
return {Kth(nl.id, x - nl.l + 1), nl.ti};
}
vector<int> V[MAXN];
int Fa[MAXN][B + 1];
LL Dep[MAXN], Dis[MAXN][B + 1], t[MAXN][B + 1];
void Dfs(int x, int fa) {
Dep[x] = Dep[fa] + 1;
for(auto &to : V[x]) {
if(to == fa) continue;
Dfs(to, x);
}
}
void Pre() {
for(int j = 1; j <= B; j++)
for(int i = 1; i <= M; i++) {
Fa[i][j] = Fa[Fa[i][j - 1]][j - 1];
t[i][j] = t[Fa[i][j - 1]][j - 1];
Dis[i][j] = Dis[i][j - 1] + Dis[Fa[i][j - 1]][j - 1];
}
}
LL calc(int x) {//计算大树中编号为x的节点到所在大节点的根的距离
Pair tmp = GetId(x);
return dep[tmp.fi] - dep[md[tmp.se].id];
}
LL Query(LL x, LL y) {//大树中编号为x, y的节点的距离
Pair bx = GetId(x), by = GetId(y);
if(bx.se == by.se) return GetDis(bx.fi, by.fi);
LL prex = x, prey = y, gx, gy;
x = bx.se; y = by.se;
if(Dep[x] < Dep[y]) swap(x, y), swap(prex, prey);
LL ans = calc(prex);
for(int i = B; ~i; i--)
if(Dep[Fa[x][i]] >= Dep[y]) {
if(Fa[x][i] == y) {
gx = GetId(t[x][i]).fi;
gy = GetId(prey).fi;
return ans + Dis[x][i] + GetDis(gx, gy) - (dep[gx] - dep[md[Fa[x][i]].id]);
}
ans += Dis[x][i], x = Fa[x][i];
}
// if(x == y) return ans - 2 * calc(prey);
for(int i = B; ~i; i--)
if(Fa[x][i] != Fa[y][i]) {
ans += Dis[x][i]; ans += Dis[y][i];
x = Fa[x][i], y = Fa[y][i];
}
gx = GetId(md[x].fa).fi, gy = GetId(md[y].fa).fi;
return ans + 2 + GetDis(gx, gy) + calc(prey);
}
signed main() {
//freopen("tree13.in", "r", stdin);freopen("b.out", "w", stdout);
N = read(); M = read() + 1; Q = read();
for(int i = 1; i <= N - 1; i++) {
int x = read(), y = read();
v[x].push_back(y);
v[y].push_back(x);
}
dfs1(1, 0);
dfs2(1, 1);//树剖
for(int i = 1; i <= N; i++) insert(root[i], root[i - 1], 1, N, rev[i]);
md[1] = {1, siz[1], 1, 0, 1};
lin.insert(md[1]);
tot = siz[1] + 1;
for(int i = 2; i <= M; i++) {
int x = read(), to = read();
md[i] = {tot, tot + siz[x] - 1, x, to, i};
lin.insert(md[i]);
tot += siz[x];
}
for(int i = 2; i <= M; i++) {
Ope x = md[i];
int u = x.ti, v = GetId(x.fa).se;//大树以操作次序来标号
V[v].push_back(u);
Dis[u][0] = dep[GetId(md[u].fa).fi] - dep[md[v].id] + 1;
Fa[u][0] = v;
t[u][0] = md[u].fa;
}
Dfs(1, 0);
Pre();
while(Q--) {
LL x = read(), y = read();
cout << Query(x, y) << '\n';
}
return 0;
}
洛谷P3248 [HNOI2016]树(主席树 倍增 )的更多相关文章
- 洛谷P2617 Dynamic Rankings (主席树)
洛谷P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a ...
- 洛谷P3567 KUR-Couriers [POI2014] 主席树/莫队
正解:主席树/莫队 解题报告: 传送门! 这题好像就是个主席树板子题的样子,,,? 毕竟,主席树的最基本的功能就是,维护一段区间内某个数字的个数 但是毕竟是刚get到主席树,然后之前做的一直是第k大, ...
- 洛谷P3567[POI2014]KUR-Couriers(主席树+二分)
题意:给一个数列,每次询问一个区间内有没有一个数出现次数超过一半 题解: 最近比赛太多,都没时间切水题了,刚好日推了道主席树裸题,就写了一下 然后 WA80 WA80 WA0 WA90 WA80 ?? ...
- 洛谷P3567 [POI2014]KUR-Couriers 主席树
挺裸的,没啥可讲的. 不带修改的主席树裸题 Code: #include<cstdio> #include<algorithm> using namespace std; co ...
- 洛谷$P3302$ 森林 $[SDOI2013]$ 主席树
正解:主席树 解题报告: 传送门! 口胡一时爽代码火葬场 这题想法不难,,,但显然的是代码应该还挺难打的 但反正我也不放代码,就写下题解趴$QwQ$ 第一问就是个$Count\ on\ a\ tree ...
- 洛谷P4602 [CTSC2018]混合果汁(主席树)
题目描述 小 R 热衷于做黑暗料理,尤其是混合果汁. 商店里有 nn 种果汁,编号为 0,1,\cdots,n-10,1,⋯,n−1 . ii 号果汁的美味度是 d_idi ,每升价格为 p_ipi ...
- 洛谷P2617 Dynamic Rankings 主席树 单点修改 区间查询第 K 大
我们将线段树套在树状数组上,查询前预处理出所有要一起移动的节点编号,并在查询过程中一起将这些节点移到左右子树上. Code: #include<cstdio> #include<cs ...
- 洛谷4137 mex题解 主席树
题目链接 虽然可以用离线算法水过去,但如果强制在线不就gg了. 所以要用在线算法. 首先,所有大于n的数其实可以忽略,因为mex的值不可能大于n 我们来设想一下,假设已经求出了从0到n中所有数在原序列 ...
- 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
随机推荐
- Office 2010激活 NO KMS products detected问题
今天用office2010激活工具Office 2010 Toolkit激活安装的office2010时悲剧的遇到了这个问题,如下图: (这张图是从网上找的,不过和我遇到的问题是一样的). 然后上网搜 ...
- Celery启动Django项目:Client sent AUTH, but no password is set 错误处理
celery -A CeleryTest worker -l info [2017-02-22 07:26:52,666: ERROR/MainProcess] consumer: Cannot co ...
- vue中请求本地的json数据
为什么要请求本地的数据?模拟后台的请求数据,验证页面的逻辑是否存在问题,抛开后台提前开发等. 常用的说来有:jq的方式 约等于 axios的方式,vuex状态管理的方式 个人认为最好用的就是jq的方式 ...
- vector源码(参考STL源码--侯捷):空间分配导致迭代器失效
vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷) vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 vector源码3(参考STL源 ...
- 业余实现一个统计A股数据工具
自己瞎捣鼓了几天 python,数据来源新浪财经,每天收盘启动爬虫抓取一遍,web 端呈现日线与周线数据:实时图表显示上证指数与个股指数等.技术点:scrapy apscheduler sqlalch ...
- 全网最详细的hive-site.xml配置文件里添加<name>hive.cli.print.header</name>和<name>hive.cli.print.current.db</name>前后的变化(图文详解)
不多说,直接上干货! 比如,你是从hive-default.xml.template,复制一份,改名为hive-site.xml 一般是 <configuration> <prope ...
- java工具类-日期工具类
1.获得时间戳 为了统一其他语言的如php和unix系统获取的时间戳是10位长度的,精确到秒. java时间戳长度是13位,精确到毫秒 我们获取时间戳需要相应处理. //获取当前时间戳,除以1000, ...
- [Python学习笔记-004] 可变参数*args和**kwargs
在Python中,可变参数的传递使用*args和**kwargs来实现,其中: *args表示任意个位置参数(positional argument),被表示为一个只读的数组(tuple): **kw ...
- SpringCloud入门之Maven系统安装及配置
一.Maven 介绍 这个单词中文翻译为“专家”或“内行”.下面将向你介绍 Maven这一跨平台的项目管理工具.作为 Apache 组织中的一个成功的开源项目,Maven 主要服务于基 Java 平台 ...
- [error] 1507#0: *22 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 10.0.0.1, server: www.wordpress.com, request: "GET /info.p
字体比较小,如果你遇到这个问题请仔细的把下面的总结看完. 环境:CentOS6.7.2.6.32-573.el6.x86_64.nginx1.12.2 .php5.5.38 问题:nginx能解析静态 ...