[CTSC2008]网络管理Network【树状数组+主席树】

2023-11-15

题目链接


题意:有一棵N个点的树,每个点有对应的权值,现在有这样的操作,“0 a b”将a点的权值改成为b,“k a b”询问a到b的链上第k大的权值是几。

  我们可以用dfs序的树上差分的方式来解决这个问题,可以发现,求u到v的信息,其实就是求u到lca和v到lca的合并,所以我们得想办法把这条链上的第k大给处理出来,这时候可以使用主席树来进行操作,我们不妨给点u赋值的时候,赋值给dfn[u]~dfn[u]+siz[u]-1,是这棵子树上的所有的点都被给予了这个值,不妨在dfn[u]位置“+1”,dfn[u]+siz[u]的位置上“-1”,用dfs序的方式将他们放到了一条链上去进行差分。

  但是现在有了修改的操作,我们改变一个值的时候,实际上会对他的所有的子树造成影响,所以我们改成给原来的每个点都是一棵主席树,我们将原来的dfs序成的序列拿出来,看成一维轴的形式,然后,就是对这个一维的轴进行操作了。

  那么,我们可以利用树状数组,对这个前缀差分来进行操作,不妨在dfn[u]的点处先减去原来的点权的贡献,再换上新的点权,然后同理不要忘记dfn[u]+siz[u]这个位置的操作。

#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 eps 1e-8
#define INF 0x3f3f3f3f
#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
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 8e4 + 7;
int N, Q, head[maxN], cnt, a[maxN], Lsan[maxN << 1], _UP;
vector<int> bin;
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); }
struct Question
{
    int k, a, b;
    void In() { scanf("%d%d%d", &k, &a, &b); }
} ques[maxN];
int siz[maxN], fa[maxN], deep[maxN], Wson[maxN];
void dfs_1(int u, int father)
{
    siz[u] = 1; fa[u] = father; deep[u] = deep[father] + 1;
    for(int i=head[u], v; ~i; i=edge[i].nex)
    {
        v = edge[i].to;
        if(v == father) continue;
        dfs_1(v, u);
        if(siz[v] > siz[Wson[u]]) Wson[u] = v;
    }
}
int top[maxN], dfn[maxN], rid[maxN], tim, End_tim[maxN];
void dfs_2(int u, int topy)
{
    top[u] = topy; dfn[u] = ++tim; rid[tim] = 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);
    }
    End_tim[u] = tim;
}
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;
}
const int max_T = maxN * 400;
int t[max_T], lc[max_T], rc[max_T], tot, root[maxN];
void Insert(int &now, int old, int l, int r, int pos, int val)
{
    if(!now) now = ++tot;
    t[now] = t[old] + val; lc[now] = lc[old]; rc[now] = rc[old];
    if(l == r) return;
    int mid = HalF;
    if(pos <= mid) Insert(lc[now], lc[old], l, mid, pos, val);
    else Insert(rc[now], rc[old], mid + 1, r, pos, val);
}
void Pre_update(int x, int pos, int val)
{
    while(x <= N)
    {
        Insert(root[x], root[x], 1, _UP, pos, val);
        x += lowbit(x);
    }
}
int tmp_1[maxN], tmp_2[maxN], t1, t2;
int query(int l, int r, int kth)
{
    int mid, sum;
    while(l ^ r)
    {
        mid = HalF; sum = 0;
        for(int i=1; i<=t1; i++) sum += t[rc[tmp_1[i]]];
        for(int i=1; i<=t2; i++) sum -= t[rc[tmp_2[i]]];
        if(sum >= kth)
        {
            for(int i=1; i<=t1; i++) tmp_1[i] = rc[tmp_1[i]];
            for(int i=1; i<=t2; i++) tmp_2[i] = rc[tmp_2[i]];
            l = mid + 1;
        }
        else
        {
            for(int i=1; i<=t1; i++) tmp_1[i] = lc[tmp_1[i]];
            for(int i=1; i<=t2; i++) tmp_2[i] = lc[tmp_2[i]];
            r = mid;
            kth -= sum;
        }
    }
    return l;
}
int Pre_Query(int u, int v, int kth)
{
    t1 = t2 = 0;
    for(int i=dfn[u]; i; i -= lowbit(i)) tmp_1[++t1] = root[i];
    for(int i=dfn[v]; i; i -= lowbit(i)) tmp_1[++t1] = root[i];
    int lca = _LCA(u, v);
    if(deep[u] + deep[v] - deep[lca] - deep[fa[lca]] < kth) return -1;
    for(int i=dfn[lca]; i; i -= lowbit(i)) tmp_2[++t2] = root[i];
    for(int i=dfn[fa[lca]]; i; i -= lowbit(i)) tmp_2[++t2] = root[i];
    return query(1, _UP, kth);
}
void dfs_3(int u, int ff)
{
    Pre_update(dfn[u], a[u], 1);
    Pre_update(End_tim[u] + 1, a[u], -1);
    for(int i=head[u], v; ~i; i=edge[i].nex)
    {
        v = edge[i].to;
        if(v == ff) continue;
        dfs_3(v, u);
    }
}
inline void init()
{
    cnt = 0; _UP = N; tim = 0; tot = 0;
    for(int i=1; i<=N; i++) head[i] = -1;
}
int main()
{
    scanf("%d%d", &N, &Q);
    for(int i=1; i<=N; i++) { scanf("%d", &a[i]); Lsan[i] = a[i]; }
    init();
    for(int i=1, u, v; i<N; i++)
    {
        scanf("%d%d", &u, &v);
        _add(u, v);
    }
    for(int i=1; i<=Q; i++) { ques[i].In(); if(!ques[i].k) Lsan[++_UP] = ques[i].b; }
    sort(Lsan + 1, Lsan + _UP + 1);
    _UP = (int)(unique(Lsan + 1, Lsan + _UP + 1) - Lsan - 1);
    for(int i=1; i<=N; i++) a[i] = (int)(lower_bound(Lsan + 1, Lsan + _UP + 1, a[i]) - Lsan);
    for(int i=1; i<=Q; i++) if(!ques[i].k) ques[i].b = (int)(lower_bound(Lsan + 1, Lsan + _UP + 1, ques[i].b) - Lsan);
    dfs_1(1, 0);
    dfs_2(1, 1);
    dfs_3(1, 0);
    int ans;
    for(int i=1; i<=Q; i++)
    {
        if(ques[i].k == 0)
        {
            Pre_update(dfn[ques[i].a], a[ques[i].a], -1);
            Pre_update(End_tim[ques[i].a] + 1, a[ques[i].a], 1);
            Pre_update(dfn[ques[i].a], ques[i].b, 1);
            Pre_update(End_tim[ques[i].a] + 1, ques[i].b, -1);
            a[ques[i].a] = ques[i].b;
        }
        else
        {
            ans = Pre_Query(ques[i].a, ques[i].b, ques[i].k);
            if(~ans)
            {
                printf("%d\n", Lsan[ans]);
            }
            else
            {
                printf("invalid request!\n");
            }
        }
    }
    return 0;
}

 

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

[CTSC2008]网络管理Network【树状数组+主席树】 的相关文章

随机推荐

  • 【JetBrains】安装使用技巧

    JetBrains 使用 JetBrains Toolbox 管理 IDE 远程开发 Gateway 通过 SSH 连接 疑难杂症 1 部署失败 使用 JetBrains Toolbox 管理 IDE 下载 Toolbox 工具 解压运行
  • Wireshark常用命令

    目录 页面 命令 不定期更新我自己遇到的语法 页面 命令 数据链路层 筛选mac地址为04 f9 38 ad 13 26的数据包 eth src 04 f9 38 ad 13 26 筛选源mac地址为04 f9 38 ad 13 26的数据
  • 模板特化

    上一篇 模板与重载 里 我遇见了想同时使用模板函数与非模板函数的情况 后来才知道 其实并不需要 当我想对某些特定的类型进行特殊操作时 只需要使用模板特化就可以 所谓特化 就是说对于模板函数 对于某些类型可能需要特殊处理 所以进行特殊化 可以
  • OpenApi-Generator:简化RESTful API开发流程

    目录 1 OpenAPI Generator简介 1 1 OpenAPI Generator是什么 1 2 为什么选择OpenAPI Generator 1 3 谁需要 OpenAPI Generator 2 OpenAPI 2 0规范 2
  • 单臂路由实现原理

    一 概述 单臂路由 router on a stick 是指在路由器的一个接口上通过配置子接口 或 逻辑接口 并不存在真正物理接口 的方式 实现原来相互隔离的不同VLAN 虚拟局域网 之间的互联互通 单臂路由的子接口 路由器的物理接口可以被
  • Python Pandas 处理空数据/缺失数据 dropna fillna,增加/更新列 assign,分层 qcut,向量函数

    Pandas 处理空数据 缺失数据 增加 更新列 分层 向量函数 数据准备 一 处理缺失数据 1 1 去除有缺失数据的行 dropna 1 2 替换缺失数据 fillna 二 增加 更新列 2 1 指定生成列的方式 2 2 复制现有的列生成
  • dataframe的索引遍历_pandas

    今天是pandas数据处理专题第三篇文章 我们来聊聊DataFrame中的索引 上篇文章当中我们简单介绍了一下DataFrame这个数据结构的一些常见的用法 从整体上大概了解了一下这个数据结构 今天这一篇我们将会深入其中索引相关的应用方法
  • 开发一个APP需要多少钱?

    作为一个移动端开发人员 我们可能被外行朋友或者被客户问及最多的一个问题就是 开发一个APP需要多少钱 不错 这个是大家特别关心的问题 也是互联网公司非常重视的一个问题 因为涉及到自己的成本问题 作为APP开发人员 站在产品经理的角度来给大家
  • windows 2008 32位IIS 服务器转到64位后的各种错误,以及解决方法

    之前在32位IIS服务器上没有问题 发布到64位出现各种错误 请检查以下几项 因各系统不一样 有则检查 无则跳过 重点第4点 1 先安装IIS 后安装 net 4 0环境 否则要重新注册iis windir Microsoft NET Fr
  • 机器学习可视化:模型评估和参数调优

    本篇文章详细阐述机器学习模型评估和参数调优 将主要围绕两个问题来阐述 知其所以然 当你选择的一个机器学习模型运行时 你要知道它是如何工作的 青出于蓝 更进一步 你得知道如何让此机器学习模型工作的更优 模型评估的方法 一般情况来说 F1评分或
  • 第四届蓝桥杯省赛JavaB组第六题三部排序

    标题 三部排序 一般的排序有许多经典算法 如快速排序 希尔排序等 但实际应用时 经常会或多或少有一些特殊的要求 我们没必要套用那些经典算法 可以根据实际情况建立更好的解法 比如 对一个整型数组中的数字进行分类排序 使得负数都靠左端 正数都靠
  • 在阿里云上运行hadoop遇到的50070,9000无法访问问题

    问题 我在阿里云上运行namenode和腾讯云上运行datanode 在hadooop配置完之后 运行hdfs 发现没有namenode 然后查看namenode的日志 日志显示50070端口被占用 9000端口拒绝服务 但是通过natst
  • vue - 实现页面全屏文字水印效果,类似 word 插入的自定义水印(支持单页或整个项目全部页面 “选择性“ 插入,可自定义水印文字、大小样式等,也能动态设置文字)和页面一同渲染,无任何卡顿示例源码

    效果图 代码干净简洁 示例源码注释详细 无任何乱七八糟的代码 本文实现了 单页或整个项目所有页面的全屏水印效果 支持自定义水印文字 可 动态 设置文字内容 你只需要复制本文提供的封装方法 直接在页面中或 App vue 中引入即可生效 只需
  • vue3+element-plus实现表格多选功能(可以清除选项或分页保留选项)

    如图所示 在实际开发中 数据量大的表格基本都添加上了分页功能 每个页面请求的数据回交换更新 第一页的选中效果在跳转至第二页后 如果没有做相关处理 选中项会被清空 具体解决方法如下 在需要处理的表格标签中加上 row key getRowKe
  • 第五章-CSRF漏洞

    第五章 CSRF漏洞 第一节 CSRF原理介绍 1 1 CSRF漏洞定义 CSRF Cross site request forery 跨站请求伪造 也被称为One Click Attack或者Session Riding 通常缩写为CSR
  • k8s组件理解

    一 k8s组件交互关系由下图可大致体现 二 k8s master组件理解 1 kube apiserver组件 kube apiserver Kubernetes kubernets API server 提供了k8s各类资源对象的增删改查
  • EasyTalking微博系统

    EasyTalking微博系统 摘要 随着互联网的迅猛发展 人们的日常生活 学习工作已经离不开网络 人们的生活和工作在未来的生活中将越来越依赖于计算机网络技术的发展 越来越网络化 电子化 虚拟化 便捷化 Internet目前的应用历程和发展
  • 如何const定义一个不可变数组

    有个常见的面试题 我们知道 const是es6中新增用于定义常量 但是对于引用类型来说 const 所说的常量 是指 对应的指针或者说地址是常量 那么 如果我们要求 我们定义的数组里面的元素也是不可改变的呢 先来看现象 const a 1
  • webgl--attribute相关使用

    attribute 是存储限定符 是专门用于向外部导出与点位相关的对象的 这类似于es6模板语法中export vec4 是变量类型 vec4是4维矢量对象 a position 是变量名 之后在js中会根据这个变量名导入变量 这个变量名是
  • [CTSC2008]网络管理Network【树状数组+主席树】

    题目链接 题意 有一棵N个点的树 每个点有对应的权值 现在有这样的操作 0 a b 将a点的权值改成为b k a b 询问a到b的链上第k大的权值是几 我们可以用dfs序的树上差分的方式来解决这个问题 可以发现 求u到v的信息 其实就是求u