poj 2104 第k大

2014/11/15


 由于一些原因,看了下主席树,原本以为很难,有幸找到了这篇博客疯狂的橡树。深入浅出,分块讲解,>.<竟然看懂了!!

这样的博客已经很少了,我一直主张境界不到少写博客,自己的博客通常也是贴代码为主(一些文字给以后的自己看),那些大牛的博客写的是很透彻,但是理解的门槛很高。

想学主席树的尽可以去看看这篇博客疯狂的橡树!!再次推荐。


现在懂了主席树了,撸到树状数组这里还有点悬,先来一发静态的。


#include<stdio.h>
#include<string.h>
#include<algorithm>

using namespace std;

const int maxm = 2555555;
const int maxn = 105000; 

int ls[maxm],rs[maxm],c[maxm];
int a[maxn],h[maxn],T[maxn];
int n, m, len, tot;

struct node{
	int l, r, k;
}sq[10005];


void init()
{
	sort(h,h+len);
	len = unique(h,h+len) - h;
}

int Hash(int x)
{
	return lower_bound(h,h+len,x) - h;
}

int build(int l,int r)
{
	int rt = tot++ , mid;
	c[rt] = 0;
	if(l < r)
	{
		mid=(l+r)>>1;
		ls[rt] = build(l,mid);
		rs[rt] = build(mid+1,r);
	}
	return rt;
}

int update(int prt,int x ,int d)//这个d在这里没用,为的是接下来的动态
{
	int srt = tot++,tp = srt, l = 0, r =len-1, mid;
	c[srt] = c[prt] + 1;
	while(l < r)
	{
		mid = (l+r)>>1;
		if(x <= mid)
		{
			rs[srt] = rs[prt],ls[srt] = tot++;
			prt = ls[prt];
			srt = ls[srt];
			r = mid;
		}
		else
		{
			ls[srt] = ls[prt],rs[srt] = tot++;
			prt = rs[prt];
			srt = rs[srt];
		        l = mid+1;
		}
		c[srt] = c[prt] + 1;
	}
	return tp;
}

int que(int l ,int r,int k)
{
   int lrt = T[l-1], srt = T[r],mid,ll = 0,rr = len-1;
   while(ll < rr)
   {
   	
   	 mid =(ll+rr)>>1;
   	 int tp = c[ls[srt]] - c[ls[lrt]];
     if(k <= tp)
     {
     	lrt = ls[lrt];
     	srt = ls[srt];
     	rr = mid;
     }
     else
     {
     	k-=tp;
     	lrt = rs[lrt];
     	srt = rs[srt];
     	ll = mid+1;
     }
   
   }
   	return ll;
}

int main()
{
	
	while(~scanf("%d%d",&n,&m))
	{
		tot=0;
		len=0;
		for(int i = 1;i <= n; i++)
		{
			scanf("%d",&a[i]);
			h[len++] = a[i];
		}

		init();
		
		T[0] = build(0,len-1);
		
		for(int i =1;i <= n; i++)
		{
			T[i] = update(T[i-1],Hash(a[i]),1);
		}
		
		for(int i = 0;i < m; i++)
		{
			scanf("%d%d%d",&sq[i].l,&sq[i].r,&sq[i].k);
		}
		
		for(int i= 0;i < m; i++)
		{
			printf("%d\n",h[que(sq[i].l,sq[i].r,sq[i].k)]);
		}
		
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值