XOR TREE【牛客练习赛58 F】【树链剖分】

2023-11-17

题目链接


 这个问题很容易想到之间的关系,假设现在所要查询的这条链上有V1、V2、…… VK个点,那么第i个点的贡献在抑或中出现的次数XOR为\large F(i) = (K - i) * i + i - 1

  • 当K为偶数时候,F(i)恒定为奇数
  • 当K为奇数的时候,F(i)在i为偶数的时候F(i)为奇数
  • 只有F(i)为奇数的时候,在抑或XOR中才有作用

  于是,如果K为偶数的时候,我们直接求这条链上所有值的抑或XOR和即可,树链剖分就可以很好的维护了。

  如果K为奇数的时候,我们需要求第2、4、6、……这几个偶数点的抑或XOR和。如果我们直接在线段树上维护当然是不行的,因为dfs序号是没有这样的独立性的,可能会有两个同时为偶数dfs序的点却是连接在一起的。

  所以考虑深度,会发现,深度奇偶不同的点一定是不相连接的,并且中间只隔了一个点。于是,我们这里开两个线段树,维护一下每个奇偶深度的抑或XOR和。

  这样,我们查询的时候,只用查询于两个结点的deep的奇偶不同的点的抑或和即可。

  因为是奇数个点,所以也代表了两个查询结点一定是在深度上同奇偶。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f3f3f3f3f
#define eps 1e-8
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
#define MAX_3(a, b, c) max(a, max(b, c))
#define Rabc(x) x > 0 ? x : -x
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
inline int read()
{
    int x=0; char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') { x=(x<<1)+(x<<3)+c-'0'; c=getchar(); }
    return x;
}
const int maxN = 2e5 + 7;
int N, Q, a[maxN], head[maxN], cnt;
struct Eddge
{
    int nex, to;
    Eddge(int a=-1, int b=0):nex(a), to(b) {}
}edge[maxN << 1];
inline void addEddge(int u, int v)
{
    edge[cnt] = Eddge(head[u], v);
    head[u] = cnt++;
}
inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); }
int siz[maxN], deep[maxN], Wson[maxN], fa[maxN];
void dfs_1(int u, int father)
{
    fa[u] = father; deep[u] = deep[father] + 1; Wson[u] = 0; siz[u] = 1;
    int maxx = 0;
    for(int i=head[u], v; ~i; i=edge[i].nex)
    {
        v = edge[i].to;
        if(v == father) continue;
        dfs_1(v, u);
        siz[u] += siz[v];
        if(maxx < siz[v])
        {
            maxx = siz[v];
            Wson[u] = v;
        }
    }
}
int top[maxN], dfn[maxN], tot, rid[maxN];
void dfs_2(int u, int topy)
{
    top[u] = topy;
    dfn[u] = ++tot; rid[tot] = u;
    if(Wson[u]) dfs_2(Wson[u], topy);
    for(int i=head[u], v; ~i; i=edge[i].nex)
    {
        v = edge[i].to;
        if(v == fa[u] || v == Wson[u]) continue;
        dfs_2(v, v);
    }
}
int tree[maxN << 2][3] = {0};
inline void pushup(int rt)
{
    tree[rt][2] = tree[lsn][2] ^ tree[rsn][2];
    tree[rt][0] = tree[lsn][0] ^ tree[rsn][0];
    tree[rt][1] = tree[lsn][1] ^ tree[rsn][1];
}
void buildTree(int rt, int l, int r)
{
    if(l == r)
    {
        tree[rt][deep[rid[l]] & 1] = a[rid[l]];
        tree[rt][2] = a[rid[l]];
        return;
    }
    int mid = HalF;
    buildTree(Lson); buildTree(Rson);
    pushup(rt);
}
void update(int rt, int l, int r, int qx, int val)
{
    if(l == r) { tree[rt][deep[rid[l]] & 1] = val; tree[rt][2] = val; return; }
    int mid = HalF;
    if(qx <= mid) update(Lson, qx, val);
    else update(Rson, qx, val);
    pushup(rt);
}
int s[3] = {0};
void query(int rt, int l, int r, int ql, int qr)
{
    if(ql <= l && qr >= r)
    {
        s[0] ^= tree[rt][0];
        s[1] ^= tree[rt][1];
        s[2] ^= tree[rt][2];
        return;
    }
    int mid = HalF;
    if(qr <= mid) query(QL);
    else if(ql > mid) query(QR);
    else { query(QL); query(QR); }
}
inline int _LCA(int u, int v)
{
    while(top[u] ^ top[v])
    {
        if(deep[top[u]] < deep[top[v]]) swap(u, v);
        u = fa[top[u]];
    }
    if(deep[u] > deep[v]) swap(u, v);
    return u;
}
inline int Range_Query(int u, int v)
{
    int ans = 0, lca = _LCA(u, v), len, op = (deep[u] & 1) ^ 1;
    int dis = deep[u] + deep[v] - 2 * deep[lca] + 1; dis &= 1;
    if(dis)
    {
        while(top[u] ^ top[v])
        {
            if(deep[top[u]] < deep[top[v]]) swap(u, v);
            len = deep[u] - deep[top[u]] + 1; len &= 1;
            s[0] = s[1] = s[2] = 0;
            query(1, 1, N, dfn[top[u]], dfn[u]);
            ans ^= s[op];
            u = fa[top[u]];
        }
        if(deep[u] < deep[v]) swap(u, v);
        len = deep[u] - deep[v] + 1; len &= 1;
        s[0] = s[1] = s[2] = 0;
        query(1, 1, N, dfn[v], dfn[u]);
        ans ^= s[op];
    }
    else
    {
        s[2] = 0;
        while(top[u] ^ top[v])
        {
            if(deep[top[u]] < deep[top[v]]) swap(u, v);
            query(1, 1, N, dfn[top[u]], dfn[u]);
            u = fa[top[u]];
        }
        if(deep[u] < deep[v]) swap(u, v);
        query(1, 1, N, dfn[v], dfn[u]);
        ans = s[2];
    }
    return ans;
}
inline void init()
{
    cnt = tot = 0;
    for(int i=1; i<=N; i++) head[i] = -1;
}
int main()
{
    N = read(); Q = read();
    init();
    for(int i=1; i<=N; i++) a[i] = read();
    for(int i=1, u, v; i<N; i++)
    {
        u = read(); v = read();
        _add(u, v);
    }
    deep[0] = 0;
    dfs_1(1, 0);
    dfs_2(1, 1);
    buildTree(1, 1, N);
    int op, x, y;
    while(Q--)
    {
        op = read(); x = read(); y = read();
        if(op == 1)
        {
            update(1, 1, N, dfn[x], y);
        }
        else
        {
            printf("%d\n", Range_Query(x, y));
        }
    }
    return 0;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XOR TREE【牛客练习赛58 F】【树链剖分】 的相关文章

  • 【QPalette】调色板简介

    描述 QPalette类包含每个小部件状态的颜色组 调色板由三个颜色组组成 活动的 禁用的和非活动的 Qt中的所有小部件都包含一个调色板 并使用它们的调色板来绘制自己 这使得用户界面易于配置和保持一致 如果您创建一个新的小部件 我们强烈建议
  • c语言常见练习题

    计算一个程序的运行时间 include

随机推荐

  • Centos系统安装Nodejs

    1 软件下载 官方网站 https nodejs org en 1 新版本下载说明 新版本可以在home页面直接下载 也可以在DOWNLOADS页面下载 2 旧版本下载说明 进入 DOWNLOADS 页面 页面滑动到最下面 点击左侧 Pre
  • PHP+jQuery+jCrop在线上传裁剪头像(内含源码)

    源码里面使用到两个开源的jQuery插件 其一是Ajax上传用的是uploadify 这个上传插件比较牛逼 并且可以自定义的东西也比较多 demo里面我用的不完善 没有把项目里面用到的取消上传和删除功能加上 同样也可以使用其他不需要使用Fl
  • 华为OD机试真题 Java 实现【矩阵稀疏扫描】【2023 B卷 100分】,附详细解题思路

    一 题目描述 如果矩阵中的许多系数都为零 那么该矩阵就是稀疏的 对稀疏现象有兴趣是因为它的开发可以带来巨大的计算节省 并且在许多大的实践中都会出现矩阵稀疏的问题 给定一个矩阵 现在需要逐行和逐列地扫描矩阵 如果某一行或者某一列内 存在连续出
  • unity 获得当前物体_Unity3D获取当前键盘按键及Unity3D鼠标、键盘的基本操作

    获取当前键盘按键 代码如下 using UnityEngine using System Collections public class GetCurrentKey MonoBehaviour KeyCode currentKey voi
  • 解决draw.io生成SVG矢量图导入Word显示有误的问题以及推荐几种SVG绘图方法

    解决draw io生成SVG矢量图导入Word显示有误的问题以及推荐几种SVG绘图方法 起因 解决办法 操作步骤 修改后效果 关于Word加载项draw io工具 流程图等推荐用Xmind 图表数据等也可以用Python的matplotli
  • centos7 基础命令

    一 linux基础 1 查看服务器的IP信息 ip add showifconfig 2 操作网卡命令 重启网络和启用网卡 systemctl restart networksystemctl start networksystemctl
  • 最近大火的两大AI绘图工具 Midjourney VS StableDiffusion

    大家好 今天给大家介绍一下最近大火的两大AI绘图工具 Midjourney 官网 和stable diffusion 官网 下面将分别从上手难易程度 出图效果 出图效率 使用成本进行对比 1 上手难易度 首先我们来看上手难易度 Midjou
  • maven2 笔记

    http blog csdn net liu251 article details 2767188 学习Mina的时候 发现Mina使用Maven做项目管理的 又开始学习Maven 这段时间做的笔记 要学会这种类似于ant 又比ant高级的
  • CSS3之3D魔方鼠标控制酷炫效果

    前面文章有制作水晶魔方 这次我们升级一下它的功能 通过鼠标控制魔方旋转 大家先看效果 这酷炫的效果 你怎么看 鼠标事件 这次效果 咱们需要用JS实现 主要是监听鼠标事件 计算鼠标滑动距离 改变魔方的rotateX rotateY JS有哪些
  • 免费代理列表

    按速度排序 http www freeproxylists net zh c cn f 1 s u 按中国搜集 http www freeproxylists net zh cn html 在线代理 http www 163 gd
  • Docker常用容器命令

    常用容器命令 有镜像才能创建容器 这是根本前提 下载一个CentOS镜像演示 docker pull centos 新建并启动容器 格式 docker run OPTIONS IMAGE COMMAND ARG 参数说明 OPTIONS说明
  • 北京课改版三年级英语教案三-Leo老师

    北京课改版三年级英语下册 I LIKE THE SHAPE Lesson2教案设计 教学目标 Objectives 推荐一个教师必备工具 Yichafen 是一个在线查分系统 全国8000所高校都在用 三分钟极速创建发布查分系统 1 确保学
  • 5月6号基金分析的那篇文章,时隔两个月收益如何?

    大家好 我是小一 在今年5月6号的时候 我写过一篇21年1季度基金持仓披露的伪分析报告 说是伪分析报告 是因为只是对 15646 只基金持仓数据中的股票型基金和混合型基金进行了简单的分析 并通过 TOP10 的持仓给出了最有可能的方向 充其
  • LDRA静态分析步骤

    将sysearch dat和sysppvar dat拷到本地 把 dat里面的所有路径替换成 要做静态分析的本地工程项目的所有头文件路径 如果有新增的新路径需要自己手动添加 通过TBvision来做静态分析 便于查看结果 创建集合 之后点C
  • c++ 将一个整数反转,例如123->321

    include
  • 封装0603和0805的区别

    封装尺寸是长x宽 0603 0805 这些单位是英寸 0603代表0 6英寸x0 3英寸 1英寸 25 4毫米 区别 一 体积大小不同 0805和0603的公制尺寸分别是2 0 1 2mm 1 6 0 8mm 所以两者的体积大小不同 二 电
  • C++面试总结

    C 内存对齐 1 内存对齐的定义 数据项只能存储在地址是数据项大小整数倍的内存位置上 现代计算机中内存空间都是按照byte划分的 从理论上讲对任何类型变量的访问可以从任何地址开始 但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问
  • Oracle集群管理-19C集群禁用numa和大页内存特性

    Linux Redhat 7 9关闭内存管理特性 1 关闭大页内存 root db1 cat sys kernel mm transparent hugepage defrag always madvise never root db1 c
  • 动态数据库切换

    JAVA基于SpringBoot动态数据库切换 1 配置数据库 数据源配置 spring datasource type com alibaba druid pool DruidDataSource driverClassName com
  • XOR TREE【牛客练习赛58 F】【树链剖分】

    题目链接 这个问题很容易想到之间的关系 假设现在所要查询的这条链上有V1 V2 VK个点 那么第i个点的贡献在抑或中出现的次数XOR为 当K为偶数时候 F i 恒定为奇数 当K为奇数的时候 F i 在i为偶数的时候F i 为奇数 只有F i