1001-Static Query on Tree
题目大意:
有一棵树,根为1,以及三个点集合A、B、C,问树上有多少个点同时满足以下条件:
- 在A中至少一点到1的路径上
- 在B中至少一点到1的路径上
- 在C中至少一点的子树中
思路:
对这棵树进行树链刨分,然后将A和B中点到1的路径打上A和B标记,在C的子树上打上C标记,然后统计同时拥有三种标记的点数量。
维护标记可以用线段树,将A标记记为1,B标记记为2,C标记记为4,当一个区间的与值为7时,说明这个区间的所有点都含有三种标记。当一个区间的或值不等于7时,说明这个区间里没有一个点拥有三种标记,就不用继续访问了(优化,否则TLE)。
另一种做法是当区间最小值为7时说明这个区间的所有点都符合,当区间最大值不等于7时说明没有点符合,两种做法理应是相同的,但是用最值的代码WA了,目前还没找到WA的原因。
AC代码:
#include <bits/stdc++.h>
const int N = 2e5 + 5;
using namespace std;
vector<int> son[N];
int fa[N], sz[N], mson[N], top[N], id[N], tot;
int minval[N * 4], maxval[N * 4], lazy[N * 4], clr[N * 4]; // clr为清除标记,将子树全部清0
void dfs1(int u)
{
sz[u] = 1;
mson[u] = 0;
for (auto v : son[u])
{
fa[v] = u;
dfs1(v);
sz[u] += sz[v];
if (sz[v] > sz[mson[u]]) mson[u] = v;
}
}
void dfs2(int u, int t)
{
top[u] = t;
id[u] = ++tot;
if (!mson[u]) return;
dfs2(mson[u], t);
for (auto v : son[u])
if (v != mson[u])
dfs2(v, v);
}
void pushdown(int u)
{
if (clr[u])
{
clr[u] = 0;
clr[u << 1] = 1;
clr[(u << 1) | 1] = 1;
lazy[u << 1] = 0;
lazy[(u << 1) | 1] = 0;
minval[u << 1] = 0;
minval[(u << 1) | 1] = 0;
maxval[u << 1] = 0;
maxval[(u << 1) | 1] = 0;
}
if (lazy[u])
{
lazy[u << 1] |= lazy[u];
minval[u << 1] |= lazy[u];
maxval[u << 1] |= lazy[u];
lazy[(u << 1) | 1] |= lazy[u];
minval[(u << 1) | 1] |= lazy[u];
maxval[(u << 1) | 1] |= lazy[u];
lazy[u] = 0;
}
}
void update(int u, int l, int r, int L, int R, int val)
{
if (l <= L && r

本文详细介绍了三道与树形结构和序列操作相关的算法问题,包括树链剖分、线段树维护标记以及动态区间操作。通过实例展示了如何使用树链剖分解决树上的路径查询,利用线段树优化区间标记统计,以及处理序列的异或和与平方和最大值问题。这些算法在处理复杂数据结构和操作时展现出高效性。
最低0.47元/天 解锁文章
108

被折叠的 条评论
为什么被折叠?



