2022”杭电杯“中国大学生算法设计超级联赛(2)1 3 11题解

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

1001-Static Query on Tree

题目大意:
有一棵树,根为1,以及三个点集合A、B、C,问树上有多少个点同时满足以下条件:

  1. 在A中至少一点到1的路径上
  2. 在B中至少一点到1的路径上
  3. 在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 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值