落谷 P3834 可持久化线段树 1(主席树)(区间第k小)

本文介绍了一种基于线段树的数据结构实现,用于高效查询指定区间内的第k小数值。通过预先处理和构建线段树,算法能够在O(log n)的时间复杂度内完成查询,适用于需要频繁进行区间查询的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设区间为l,r,用r版本减去l版本求出区间第k小,一个板子

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
struct node1
{
    int v;
    int po;
}ed[500005];
struct node2
{
    int v;
    int vy;
}ed2[500005];
int cmp(node1 a,node1 b)
{
    return a.v<b.v;
}
int cnt;
int root[500005];
int tval[500005];
struct Tree
{
    int lson;
    int rson;
    int val;
}tree[500005*30];
void insert(int &rt,int ort,int l,int r,int po,int val)
{
    if(!rt)rt=++cnt;
    if(l==r)
    {
        tree[rt].val=tree[ort].val+val;
        return;
    }
    int mid=(l+r)/2;
    if(po<=mid)
    {
        tree[rt].rson=tree[ort].rson;
        insert(tree[rt].lson,tree[ort].lson,l,mid,po,val);
    }else
    {
        tree[rt].lson=tree[ort].lson;
        insert(tree[rt].rson,tree[ort].rson,mid+1,r,po,val);
    }
    tree[rt].val=tree[tree[rt].lson].val+tree[tree[rt].rson].val;
}
int query(int rt,int ort,int l,int r,int k)
{
    if(!rt)return 0;
    int mid=(l+r)/2;
    if(l==r)
    {
        return l;
    }
    if(k<=tree[tree[rt].lson].val-tree[tree[ort].lson].val)
    {
        return query(tree[rt].lson,tree[ort].lson,l,mid,k);
    }else
    {
        k-=tree[tree[rt].lson].val-tree[tree[ort].lson].val;
        return query(tree[rt].rson,tree[ort].rson,mid+1,r,k);
    }
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++)
    {
        scanf("%d",&ed[i].v);
        ed[i].po=i;
    }
    sort(ed+1,ed+1+n,cmp);
    int tt=1;
    ed2[ed[1].po].v=1;
    ed2[ed[1].po].vy=ed[1].v;
    for(int i = 2;i <= n;i++)
    {
        if(ed[i].v!=ed[i-1].v)
        {
            ed2[ed[i].po].v=++tt;
            ed2[ed[i].po].vy=ed[i].v;
        }else
        {
            ed2[ed[i].po].v=tt;
            ed2[ed[i].po].vy=ed[i].v;
        }
    }
    for(int i = 1;i <= n;i++)
    {
        insert(root[i],root[i-1],1,tt,ed2[i].v,1);
        tval[ed2[i].v]=ed2[i].vy;
    }
    for(int i = 1;i <= m;i++)
    {
        int a,b,kk;
        scanf("%d%d%d",&a,&b,&kk);
        int ty=query(root[b],root[a-1],1,tt,kk);
        printf("%d\n",tval[ty]);
    }
    return 0;
}

 

### 关于洛谷平台上的乒乓球问题解决方案 对于洛谷平台上涉及乒乓球问题的解决方法,在C语言中的实现可以基于动态规划的思想来处理。给定的问题描述似乎并不完全匹配所提供的代码片段,该片段主要关注最长上升子序列(Longest Increasing Subsequence, LIS),而非具体的乒乓球比赛逻辑[^1]。 然而,如果考虑的是类似于计算得分、判断胜负等典型的乒乓球竞赛场景下的编程挑战,则通常会涉及到输入双方选手的比赛分数,并依据特定规则决定最终胜者或是展示比分变化过程等问题。下面给出一段简化版的模拟乒乓球赛制下判定胜利者的C语言程序: ```c #include <stdio.h> int main() { int scoreA = 0; int scoreB = 0; char winner; while (scoreA < 21 && scoreB < 21 || abs(scoreA - scoreB) <= 1) { // 假设采用21分制且需领先两分获胜 scanf("%d %d", &scoreA, &scoreB); // 输入当前回合后的累计分数 if ((scoreA >= 21 && scoreA - scoreB >= 2)) { winner = 'A'; break; } if ((scoreB >= 21 && scoreB - scoreA >= 2)) { winner = 'B'; break; } } printf("The match ends with player %c as the winner.\n", winner); return 0; } ``` 此段代码仅作为示例展示了如何通过循环读取每轮次之后两位玩家各自的总分并据此确定哪位玩家赢得了整场比赛。实际比赛中可能还需要考虑到更多细节如发球权转换、局间休息等情况,这取决于具体题目要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值