题目传送门

https://lydsy.com/JudgeOnline/problem.php?id=4448

题解

练习一下主席树的基础练习题找回感觉。

对于每一次询问,第一问显然随便做。

第二问的话,可以发现就是要求出路径上的加入时间小于 \(i - c - 1\) 的点。

这个东西似乎可以树上动态主席树?

其实我们可以发现,后面加入的点对前面的查询没有影响,所以我们可以先一起吧整棵树上的点的加入时间都查出来,然后询问加入时间小于 \(i-c+1\) 的点。

查询的时候可以用树上差分,就是加上 \(x, y\) 的树上前缀和,减去 \(lca\) 和 \(fa[lca]\)。


时间复杂度 \(q\log n\)。

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
} const int N = 2e5 + 7; int n, m, rr, dfc, nod;
int f[N], tt[N], rt[N];
int dep[N], siz[N], son[N], top[N], dfn[N], pre[N]; struct Query { int x, y, c; } q[N]; struct Edge { int to, ne; } g[N << 1]; int head[N], tot;
inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y) { addedge(x, y), addedge(y, x); } struct Node { int lc, rc, val; } t[N * 20];
inline void ins(int &o, int p, int L, int R, int x) {
t[o = ++nod] = t[p], ++t[o].val;
if (L == R) return;
int M = (L + R) >> 1;
if (x <= M) ins(t[o].lc, t[p].lc, L, M, x);
else ins(t[o].rc, t[p].rc, M + 1, R, x);
}
inline int qsum(int o1, int o2, int o3, int o4, int L, int R, int l, int r) {
if (l > r) return 0;
if (l <= L && R <= r) return t[o1].val + t[o2].val - t[o3].val - t[o4].val;
int M = (L + R) >> 1;
if (r <= M) return qsum(t[o1].lc, t[o2].lc, t[o3].lc, t[o4].lc, L, M, l, r);
if (l > M) return qsum(t[o1].rc, t[o2].rc, t[o3].rc, t[o4].rc, M + 1, R, l, r);
return qsum(t[o1].lc, t[o2].lc, t[o3].lc, t[o4].lc, L, M, l, r) + qsum(t[o1].rc, t[o2].rc, t[o3].rc, t[o4].rc, M + 1, R, l, r);
} inline void dfs1(int x, int fa = 0) {
if (tt[x]) ins(rt[x], rt[fa], 1, m, tt[x]);
else rt[x] = rt[fa];
dep[x] = dep[fa] + 1, f[x] = fa, siz[x] = 1;
for fec(i, x, y) if (y != fa) dfs1(y, x), siz[x] += siz[y], siz[y] > siz[son[x]] && (son[x] = y);
}
inline void dfs2(int x, int pa) {
top[x] = pa, dfn[x] = ++dfc, pre[dfc] = x;
if (!son[x]) return; dfs2(son[x], pa);
for fec(i, x, y) if (y != f[x] && y != son[x]) dfs2(y, y);
}
inline int lca(int x, int y) {
while (top[x] != top[y]) dep[top[x]] > dep[top[y]] ? x = f[top[x]] : y = f[top[y]];
return dep[x] < dep[y] ? x : y;
} inline void work() {
dfs1(rr), dfs2(rr, rr);
for (int i = 1; i <= m; ++i) if (q[i].x) {
int x = q[i].x, y = q[i].y, c = q[i].c, p = lca(x, y);
printf("%d %d\n", dep[x] + dep[y] - (dep[p] << 1) + 1, qsum(rt[x], rt[y], rt[p], rt[f[p]], 1, m, 1, i - c - 1));
}
} inline void init() {
read(n);
for (int i = 1; i <= n; ++i) read(f[i]), f[i] == 0 && (rr = i), f[i] && (addedge(f[i], i), 0);
read(m);
for (int i = 1; i <= m; ++i) {
int opt, x;
read(opt);
if (opt == 2) read(x), tt[x] = i;
else read(q[i].x), read(q[i].y), read(q[i].c);
}
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}

bzoj4448 [Scoi2015]情报传递 主席树+树上差分的更多相关文章

  1. BZOJ4448[Scoi2015]情报传递——主席树+LCA

    题目描述 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员口J-能有 若T名(可能没有)下线,除1名大头目外其余n-1名情报员有且仅有1名上线.奈特公司纪律森严 ...

  2. 【BZOJ4448】[Scoi2015]情报传递 主席树+LCA

    [BZOJ4448][Scoi2015]情报传递 Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员能有若干名(可能没有)下线,除1名大头 ...

  3. 【bzoj4448】[Scoi2015]情报传递 主席树

    题目描述 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员口J-能有若T名(可能没有)下线,除1名大头日外其余n-1名情报员有且仅有1名上线.奈特公司纪律森严, ...

  4. BZOJ2588 主席树 + 树上差分

    https://www.lydsy.com/JudgeOnline/problem.php?id=2588 题意:强制在线的询问树链权值第K小(无修) 这种类似于第K小的题,一般容易想到主席树,但是树 ...

  5. bzoj 4448 [Scoi2015]情报传递 主席树

    比较套路的题目. 可以发现难点在于某个点的权值动态修改 且我们要维护树上一条路径上的点权>x的个数. 每个点都在动态修改 这意味着我们的只能暴力的去查每个点. 考虑将所有可以动态修改的点变成静态 ...

  6. 4448: [Scoi2015]情报传递|主席树|离线操作

    能够把全部的操作离线,然后树链剖分将全部人搜集情报的时间增加到主席树中,查询的时候能够直接查询搜集情报时间≤i−C[i]−1的人的个数 时间复杂度n∗log22n,空间复杂度n∗log2n #incl ...

  7. [BZOJ 4771]七彩树(可持久化线段树+树上差分)

    [BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...

  8. BZOJ4448 SCOI2015情报传递(离线+树链剖分+树状数组)

    即滋磁单点修改,询问路径上小于某数的值有多少个.暴力树剖套个主席树(或者直接树上主席树,似乎就1个log了?感觉不一定比两个log快)即可,然而不太优美. 开始觉得可以cdq,然而就变成log^3了. ...

  9. 洛谷P4216 [SCOI2015]情报传递(树剖+主席树)

    传送门 我们可以进行离线处理,把每一个情报员的权值设为它开始收集情报的时间 那么设询问的时间为$t$,就是问路径上有多少个情报员的权值小于等于$t-c-1$ 这个只要用主席树上树就可以解决了,顺便用树 ...

随机推荐

  1. RHEL6 kernel bug在hadoop上的测试

    最近给hadoop集群升级了RHEL6,发现性能比之前的差了不少.发现淘宝内核组发现并解决了这个问题 原文链接:http://blog.donghao.org/2013/03/20/hadoop%E9 ...

  2. Oracle诊断: 服务器启后,无法连接

    Oracle 服务器启后,使用Toad 客户端连接oracle 时候,遇到下面的错误: oracle ORA-12514: TNS: no listener TNS: listener does no ...

  3. tab下图表展示宽高为0的问题

    tab下,默认展示第一个tab(最新订阅),第二个tab是echarts,需要动态获取父级div的宽高并赋值到图表的DOM的宽高.在实际开发过程中,发现无论如何延迟处理,或者mounted,第二个ta ...

  4. 自定义控件 - 切换开关:SwitchView

    自定义控件一般的几个步骤:1.初始化相关背景图片,布局文件,自定义属性2.设置控件宽高OnMeasure()3.布局或者排版OnLayout()4.绘制控件OnDraw()5.处理触摸事件OnTouc ...

  5. Eclipse的switch workspace 选项中删除多余的workspace

    方法1 Eclipse图形化工具: 打开Eclipse后,选择功能菜单里的Windows->Preferences->,弹出对话框后,选择General->Startup and S ...

  6. javamail 附件以及正文加图片

    直接上代码 import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.uti ...

  7. log4j.properties 输出指定类日志

    比如,我只要众多日志中,红色框的日志,则可以指定类:com.dangdang.ddframe.rdb.sharding.parser.SQLParserFactory 修改配置文件: 再次输出结果为:

  8. npm 中的 --

    -- 命令告诉cli-parser停止向下解析, --后面的内容会传给命令行作为命令行参数 文档地址: https://docs.npmjs.com/misc/config.html

  9. malloc函数分配内存失败的常见原因

    malloc()函数分配内存失败的常见原因:  1. 内存不足.  2. 在前面的程序中出现了内存的越界访问,导致malloc()分配函数所涉及的一些信息被破坏.下次再使用malloc()函数申请内存 ...

  10. C++ 全面刨析使用指针方法 _new _delete

    指针 #include<iostream> using namespace std; int main() { ; int* pn;//声明 int* pn = &avr;//初始 ...