BZOJ 2223: [Coci 2009]PATULJCI

本文介绍了一种使用主席树解决区间中位数问题的方法。通过构建主席树,可以高效地查询区间内的中位数个数是否超过一定阈值。文章详细解释了算法原理,包括如何构建和查询主席树,以及为什么选择中位数作为关键指标。

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

看题面戳我

因为给了上限,言外之意算法与数据的上限有关,猜测是数组,但想一想不可能,所以应该是权值线段树

综合一下,猜测应该是区间第K大,也就是主席树了

最暴力的做法:每次询问排序后查看是否有连续超过\frac{r-l+1}{2}的数相同

Q:为什么要是超过\frac{r-l+1}{2}的数相同呢?为什么不能在给一个数据呢?

A:这是区间的一半,排序后如果存在则相同的数必须为中位数,证明略

所以结论与之前的猜想一结合,就是求区间的中位数的个数是否超过\frac{r-l+1}{2}

这与权值线段树上一个点的值就是下标的个数的思想完全匹配,所以就是一颗主席树

#include<cstdio>
#include<iostream>
using namespace std;
 
const int N=4500000,M=3e5+5;;
int n,m,T,ans,rt[M];
 
struct A
{
    int lc[N],rc[N],c[N],cnt;
    void add(int &p,int l,int r,int x)
    {
        lc[++cnt]=lc[p],rc[cnt]=rc[p],c[cnt]=c[p]+1,p=cnt;
        if(l==r) return;
        int mid=l+r>>1;
        if(mid>=x) add(lc[p],l,mid,x);
            else add(rc[p],mid+1,r,x);
    }
     
    int kth(int p1,int p2,int l,int r,int k,int bz)
    {
        if(l==r) return c[p2]-c[p1]>bz?l:0;  //判断是否>r-l+1>>1,bz表示标准 
        int mid=l+r>>1,xx=c[lc[p2]]-c[lc[p1]];
        if(xx>=k) return kth(lc[p1],lc[p2],l,mid,k,bz);
        return kth(rc[p1],rc[p2],mid+1,r,k-xx,bz);
    }
}tree;
 
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) 
	{
		int x; scanf("%d",&x);
		rt[i]=rt[i-1],tree.add(rt[i],1,m,x);
	}  //建树 
    scanf("%d",&T);
    while(T--)
    {
        int l,r; scanf("%d%d",&l,&r);
        ans=tree.kth(rt[l-1],rt[r],1,m,r-l+2>>1,r-l+1>>1); //查找中位数 
        if(!ans) puts("no"); else printf("yes %d\n",ans);
    }
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值