HDU 6278
题意:就是求区间内第k大的值大于等于k时的最大的k。
思路:很明显二分求这个最大的k,再用主席树求第k大的值来判断是否大于等于k。
#include
#include
#include
using namespace std;
const int maxn=1e5+5;
int a[maxn],b[maxn],rt[maxn*20],ls[maxn*20],rs[maxn*20],sum[maxn*20];
int cnt,ql,qr,k;
void build(int& o,int l,int r)
{
o=++cnt;
sum[o]=0;
if(l==r)
return;
int m=(l+r)/2;
build(ls[o],l,m);
build(rs[o],m+1,r);
}
void update(int pre,int& o,int l,int r,int pos)
{
o=++cnt;
ls[o]=ls[pre];
rs[o]=rs[pre];
sum[o]=sum[pre]+1;
if(l==r)
return;
int m=(l+r)/2;
if(pos<=m)
update(ls[pre],ls[o],l,m,pos);
else
update(rs[pre],rs[o],m+1,r,pos);
}
int query(int pre,int o,int l,int r)
{
if(l==r)
return b[l];
int m=(l+r)/2;
int cmp=sum[ls[o]]-sum[ls[pre]];
if(cmp>=k)
return query(ls[pre],ls[o],l,m);
else
{
k-=cmp;
return query(rs[pre],rs[o],m+1,r);
}
}
void work(int sz)
{
scanf("%d%d",&ql,&qr);
int L=1,R=qr-ql+2,m;//把最大值+1,去解决二分自带的bug
while(L=m)
{
if(L==m)
break;
L=m;
}
else
R=m;
}
printf("%d\n",m);
}
int main()
{
int n,q,i;
while(~scanf("%d%d",&n,&q))
{
for(i=1;i<=n;i++)
{
scanf("%d",&b[i]);
a[i]=b[i];
}
sort(b+1,b+n+1);
int sz=unique(b+1,b+1+n)-(b+1);
cnt=0;
build(rt[0],1,sz);
for(i=1;i<=n;i++)
a[i]=lower_bound(b+1,b+1+sz,a[i])-b;
for(i=1;i<=n;i++)
update(rt[i-1],rt[i],1,sz,a[i]);
while(q--)
work(sz);
}
}