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;
}