题意

给定一棵 \(n\) 个点的带点权树,以 \(1\) 为根, \(m\) 次询问,每次询问给出两个值 \(p, k\) ,求以下值:

\(p\) 的子树中距离 \(p \le k\) 的所有点权最小值,询问强制在线。

\(n \le 10^5 , m \le 10^6, TL = 6s\)

题解

如果不强制在线,直接线段树合并就做完了。

强制在线,不难想到用一些可持久化的结构来维护这些东西。

其实可以类似线段树合并那样考虑,也就是说每次合并的时候我们依然使用儿子的信息。

只要在合并 \(x, y\) 共有部分的时候建出新节点,然后权值是 \(x, y\) 权值的较小值,其他的部分直接连向那些单独有的子树信息即可。

其实实现是这样的:

	int Merge(int x, int y) {
if (!x || !y) return x | y;
int o = Newnode();
ls[o] = Merge(ls[x], ls[y]);
rs[o] = Merge(rs[x], rs[y]);
minv[o] = min(minv[x], minv[y]);
return o;
}

这样的话,既可以保留子树信息,又可以得到这个节点新的信息。

最后空间复杂度就是 \(O(n \log n)\) ,时间复杂度是 \(O((n + m) \log n)\) 的。

总结

强制在线问题,用可持久化数据结构去解决就行了,也就是把平常的数据结构记历史版本,并尽量用之前的信息。

代码

#include <bits/stdc++.h>

#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define pb push_back using namespace std; template<typename T> inline bool chkmin(T &a, T b) {return b < a ? a = b, 1 : 0;}
template<typename T> inline bool chkmax(T &a, T b) {return b > a ? a = b, 1 : 0;} inline int read() {
int x(0), sgn(1); char ch(getchar());
for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;
for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);
return x * sgn;
} void File() {
#ifdef zjp_shadow
freopen ("F.in", "r", stdin);
freopen ("F.out", "w", stdout);
#endif
} const int N = 1e5 + 1e3, inf = 0x3f3f3f3f; #define lson ls[o], l, mid
#define rson rs[o], mid + 1, r template<int Maxn>
struct Chair_Man_Tree { int ls[Maxn], rs[Maxn], minv[Maxn], Size; Chair_Man_Tree() { minv[0] = inf; } inline int Newnode() {
int o = ++ Size; minv[o] = inf; return o;
} void Update(int &o, int l, int r, int up, int uv) {
if (!o) o = Newnode();
if (l == r) { chkmin(minv[o], uv); return ; }
int mid = (l + r) >> 1;
up <= mid ? Update(lson, up, uv) : Update(rson, up, uv);
minv[o] = min(minv[ls[o]], minv[rs[o]]);
} int Query(int o, int l, int r, int ql, int qr) {
if (!o) return inf;
if (ql <= l && r <= qr) return minv[o];
int mid = (l + r) >> 1;
if (qr <= mid) return Query(lson, ql, qr);
if (ql > mid) return Query(rson, ql, qr);
return min(Query(lson, ql, qr), Query(rson, ql, qr));
} int Merge(int x, int y) {
if (!x || !y) return x | y;
int o = Newnode();
ls[o] = Merge(ls[x], ls[y]);
rs[o] = Merge(rs[x], rs[y]);
minv[o] = min(minv[x], minv[y]);
return o;
} }; vector<int> G[N]; int val[N], rt[N], dep[N]; int n, S; Chair_Man_Tree<N * 80> T; void Dfs(int u, int fa = 0) {
dep[u] = dep[fa] + 1;
for (int v : G[u]) if (v != fa)
Dfs(v, u), rt[u] = T.Merge(rt[u], rt[v]);
T.Update(rt[u], 1, n, dep[u], val[u]);
} int main () { File(); n = read(); S = read(); For (i, 1, n)
val[i] = read(); For (i, 1, n - 1) {
int u = read(), v = read();
G[u].pb(v); G[v].pb(u);
} Dfs(S); int q = read(), ans = 0;
For (i, 1, q) {
int x = (read() + ans) % n + 1, k = (read() + ans) % n;
printf ("%d\n", ans = T.Query(rt[x], 1, n, dep[x], min(dep[x] + k, n)));
} return 0; }

Educational Codeforces Round 33 (Rated for Div. 2) F. Subtree Minimum Query(主席树合并)的更多相关文章

  1. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...

  2. Educational Codeforces Round 71 (Rated for Div. 2)-F. Remainder Problem-技巧分块

    Educational Codeforces Round 71 (Rated for Div. 2)-F. Remainder Problem-技巧分块 [Problem Description] ​ ...

  3. [Educational Codeforces Round 81 (Rated for Div. 2)]E. Permutation Separation(线段树,思维,前缀和)

    [Educational Codeforces Round 81 (Rated for Div. 2)]E. Permutation Separation(线段树,思维,前缀和) E. Permuta ...

  4. Educational Codeforces Round 33 (Rated for Div. 2) E. Counting Arrays

    题目链接 题意:给你两个数x,yx,yx,y,让你构造一些长为yyy的数列,让这个数列的累乘为xxx,输出方案数. 思路:考虑对xxx进行质因数分解,设某个质因子PiP_iPi​的的幂为kkk,则这个 ...

  5. Educational Codeforces Round 33 (Rated for Div. 2) 题解

    A.每个状态只有一种后续转移,判断每次转移是否都合法即可. #include <iostream> #include <cstdio> using namespace std; ...

  6. Educational Codeforces Round 33 (Rated for Div. 2)A-F

    总的来说这套题还是很不错的,让我对主席树有了更深的了解 A:水题,模拟即可 #include<bits/stdc++.h> #define fi first #define se seco ...

  7. Educational Codeforces Round 33 (Rated for Div. 2) D. Credit Card

    D. Credit Card time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  8. Educational Codeforces Round 33 (Rated for Div. 2) C. Rumor【并查集+贪心/维护集合最小值】

    C. Rumor time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  9. Educational Codeforces Round 33 (Rated for Div. 2) B. Beautiful Divisors【进制思维/打表】

    B. Beautiful Divisors time limit per test 2 seconds memory limit per test 256 megabytes input standa ...

随机推荐

  1. 最全的Django入门及常用配置

    Django 常用配置 Django 安装 pipx install django x 为python解释器版本2 or 3 如果你想安装指定版本的django,使用pip install djang ...

  2. sql学习内容记录

    1.left函数 left(字段,长度):获取指定字段左侧的数据,类似substring函数 2.union / union all 将多个记录合并成一个完整的数据集 3.insert into se ...

  3. C#中闭包的陷阱

    我们在使用lambda的时候会遇到闭包,在闭包中有一个陷阱是在for循环中产生的,先上代码: class Program { static void Main(string[] args) { Act ...

  4. Linux 查找文件命令 find whereis locate

    Linux 有三个查找文件的命令:find, whereis, locate 其中find 不常用,whereis与locate经常使用,因为find命令速度较慢,因为whereis与locate是利 ...

  5. Linux 查询oracle错误日志&警告日志

    1 通过命令查看错误日志目录:show parameter background_dump_dest /usr/oracle/app/diag/rdbms/orcl/orcl/trace   2 根据 ...

  6. 20181114教学sql

    --精确查找:查询水表编号为30408的业主记录 ' --模糊查询:查询业主名称包含'刘'的业主记录 SELECT * FROM T_OWNERS WHERE NAME LIKE '%刘%' --AN ...

  7. BPM与OA的区别

    近年来,随着计算机技术的发展和互联网时代的到来,我们已经进入了信息时代,也称为数字化时代,在这数字化的时代里,企业的经营管理都受到了极大的挑战.从上世纪90年代起至今,企业的信息化工作开展的如火如荼, ...

  8. Vue 鼠标移入移出事件

    Vue 中鼠标移入移出事件 @mouseover和@mouseleave 然后绑定style   现在开始代码示例 <template> <div class="pc&qu ...

  9. React 避免重渲染

    组件的重新渲染 我们可以在 React 组件中的 props 和 state 存放任何类型的数据,通过改变 props 和 state,去控制整个组件的状态.当 props 和 state 发生变化时 ...

  10. Mapper动态代理方式

    开发规范 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同Dao接口实现类方法. Mapper接 ...