首页 > 其他分享 >洛谷题单指南-线段树的进阶用法-P2617 Dynamic Rankings

洛谷题单指南-线段树的进阶用法-P2617 Dynamic Rankings

时间:2025-01-16 09:20:57浏览次数:1  
标签:tmpl return 进阶 ops int 洛谷题 Dynamic tr tmpr

原题链接:https://www.luogu.com.cn/problem/P2617

题意解读:动态求区间第k小问题。

解题思路:树套树的典型应用,具体阐述参考:https://www.cnblogs.com/jcwy/p/18640914

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 100005;

struct Op
{
    char op;
    int l, r, k;
    int x, y;
} ops[N];

struct Node
{
    int L, R;
    int cnt;
} tr[N * 400];

int root[N], idx;
int a[N];
vector<int> b; //用于离散化
vector<int> tmpl, tmpr; //缓存查询的根节点
int n, m;

//获取x离散化之后的值
int lsh(int x)
{
    return lower_bound(b.begin(), b.end(), x) - b.begin() + 1;
}

int lowbit(int x)
{
    return x & -x;
}

void pushup(int u)
{
    tr[u].cnt = tr[tr[u].L].cnt + tr[tr[u].R].cnt;
}

//将根为u的线段树中值val的数量增加add
int update(int u, int l, int r, int val, int num)
{
    if(!u) u = ++idx;
    if(l == r)
    {
        tr[u].cnt += num;
        return u;
    }
    int mid = l + r >> 1;
    if(val <= mid) tr[u].L = update(tr[u].L, l, mid, val, num);
    else tr[u].R = update(tr[u].R, mid + 1, r, val, num);
    pushup(u);
    return u;
}

//在根为tmpr、tmpl的线段树查询第k小值
//左子树的元素数量=tmpr所有线段树左子树的元素数量-tmpl所有线段树左子树的元素数量
int query(int l, int r, int k)
{
    if(l == r) return l;
    int res = 0;
    for(int i = 0; i < tmpr.size(); i++) res += tr[tr[tmpr[i]].L].cnt;
    for(int i = 0; i < tmpl.size(); i++) res -= tr[tr[tmpl[i]].L].cnt;
    int mid = l + r >> 1;
    if(res >= k)
    {
        for(int i = 0; i < tmpr.size(); i++) tmpr[i] = tr[tmpr[i]].L;
        for(int i = 0; i < tmpl.size(); i++) tmpl[i] = tr[tmpl[i]].L;
        return query(l, mid, k);
    }
    else
    {
        for(int i = 0; i < tmpr.size(); i++) tmpr[i] = tr[tmpr[i]].R;
        for(int i = 0; i < tmpl.size(); i++) tmpl[i] = tr[tmpl[i]].R;
        return query(mid + 1, r, k - res);
    }
}

//利用树状数组将root[pos]~root[n]线段树中值val的数量加num
void add(int pos, int val, int num)
{
    for(int i = pos; i <= n; i += lowbit(i))
        root[i] = update(root[i], 1, b.size(), val, num);
}   

//利用树状数组在root[l]~root[r]线段树中查询第k小的值
int find_kth(int l, int r, int k)
{
    tmpr.clear();
    tmpl.clear();
    //缓存要查询的root[1]~root[r]的值涉及的线段树根节点
    for(int i = r; i; i -= lowbit(i)) tmpr.push_back(root[i]);
    //缓存要查询的root[1]~root[l-1]的值涉及的线段树根节点
    for(int i = l - 1; i; i -= lowbit(i)) tmpl.push_back(root[i]);
    return query(1, b.size(), k);
}

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        b.push_back(a[i]);
    }
    for(int i = 1; i <= m; i++)
    {
        cin >> ops[i].op;
        if(ops[i].op == 'Q') cin >> ops[i].l >> ops[i].r >> ops[i].k;
        else if(ops[i].op == 'C')
        {
            cin >> ops[i].x >> ops[i].y;
            b.push_back(ops[i].y);
        }
    }

    //排序,去重,用于离散化
    sort(b.begin(), b.end());
    b.erase(unique(b.begin(), b.end()), b.end());

    for(int i = 1; i <= n; i++) add(i, lsh(a[i]), 1);
    for(int i = 1; i <= m; i++)
    {
        if(ops[i].op == 'Q')
        {
            cout << b[find_kth(ops[i].l, ops[i].r, ops[i].k) - 1] << endl;
        }
        else if(ops[i].op == 'C')
        {
            add(ops[i].x, lsh(a[ops[i].x]), -1);
            a[ops[i].x] = ops[i].y;
            add(ops[i].x, lsh(a[ops[i].x]), 1);
        }
    }
}

 

标签:tmpl,return,进阶,ops,int,洛谷题,Dynamic,tr,tmpr
From: https://www.cnblogs.com/jcwy/p/18673073

相关文章

  • AI 编程工具—Cursor进阶使用 阅读开源项目
    AI编程工具—Cursor进阶使用阅读开源项目首先我们打开一个最近很火的项目browser-use,直接从github上克隆即可索引整个代码库这里我们使用@Codebase这个选项会索引这个代码库,然后我们再选上这个项目的README.md文件开始提问@Codebase@README.md这个项目是用......
  • 【进阶教程】轻量级开源VNC本地安装与跨平台远程桌面实战分享——“cpolar内网穿透”
    文章目录前言1.安装TightVNC服务端2.局域网VNC远程测试3.Win安装Cpolar工具4.配置VNC远程地址5.VNC远程桌面连接6.固定VNC远程地址7.固定VNC地址测试前言在工作和生活中,我们经常需要跨越地理界限进行协作或处理事务。这时,远程桌面服务就成了不可或缺的好帮手......
  • PHP语法进阶
    PHP语法进阶数组数组能够在单个变量中存储多个值,并且可以根据键访问其中的值PHP有两种数组:数值数组、关联数组。数值和关联两个词都是针对数组的键而言的。先介绍下数值数组,数值数组是指数组的键是整数的数组,并且键的整数顺序是从0开始,依次类推。数值数组$maoshu=ar......
  • Tauri教程-进阶篇-第二节 命令机制
    “如果结果不如你所愿,就在尘埃落定前奋力一搏。”——《夏目友人帐》“有些事不是看到了希望才去坚持,而是因为坚持才会看到希望。”——《十宗罪》“维持现状意味着空耗你的努力和生命。”——纪伯伦Tauri技术教程*第五章Tauri的进阶教程第二节命令机制一.......
  • Tauri教程-进阶篇-第一节 自定义启动画面
    “如果结果不如你所愿,就在尘埃落定前奋力一搏。”——《夏目友人帐》“有些事不是看到了希望才去坚持,而是因为坚持才会看到希望。”——《十宗罪》“维持现状意味着空耗你的努力和生命。”——纪伯伦Tauri技术教程*第五章Tauri的进阶教程第一节自定义启动画面......
  • 针对 Dynamics 365 CRM 系列产品的开发,目前的最佳实践技术栈可以从前端、后端、集成工
    针对Dynamics365CRM系列产品的开发,目前的最佳实践技术栈可以从前端、后端、集成工具、开发工具等几个方面来推荐。以下是结合实际开发需求和社区常见技术趋势的综合推荐:1.前端技术栈Dynamics365CRM中的前端开发主要用于扩展UI(如表单、视图、Ribbon按钮等)。推荐技术 1......
  • K8S之Pod进阶
    文章目录容器容器的状态pod实例配置镜像仓库拉镜像默认值特别说明容器重启策略Init容器Init容器优势Init容器实例特殊说明临时容器hook钩子函数容器探针何时该使用启动探针Pause(Infra)容器背景实现Pause容器的作用PodPreset如何工作容器容器的状态容器的状......
  • 敏捷团队的进阶之路:工具的实践与应用
    ​在当今快节奏、高竞争的商业环境中,“敏捷”已经从一种开发模式演变为广泛适用于各行业的工作哲学。然而,对于很多团队来说,敏捷并不仅仅是学习几个概念或框架,更是如何在日常实践中将这些理念真正落地。而在这个过程中,敏捷工具的作用显得尤为重要。为什么敏捷工具成为敏捷落地的......
  • AIGC从入门到实战:进阶:魔法打败魔法,让 AI 自动生成提示词
    AIGC,提示词生成,自然语言处理,深度学习,Transformer,预训练模型,算法原理,实践应用1.背景介绍近年来,人工智能生成内容(AIGC)技术蓬勃发展,以其强大的文本生成能力,在创作、翻译、摘要等领域展现出巨大的潜力。然而,AIGC的应用离不开高质量的提示词,而手工撰写提示词......
  • 织梦CMS进阶 - 修改织梦网站模板的详细步骤与实用技巧
    织梦(DedeCMS)是一款流行的开源内容管理系统,广泛应用于企业官网和个人博客建设。以下是关于如何修改织梦网站模板的一些基本指导和高级技巧:登录后台管理界面使用管理员账号登录织梦后台,进入“模板管理”模块。在这里您可以上传、编辑或删除现有的模板文件。同时,通过修改CSS文件来......