标签:des style blog http os 2014
1 10 10 0 5 2 7 5 4 3 8 7 7 2 8 6 3 5 0 1 3 1 1 9 4 0 1 0 3 5 5 5 5 1 4 6 3 1 5 7 5 7 3
Case 1: 4 0 0 3 1 2 0 1 5 1
思路:求区间内不大于给定数的最大数在该区间的第K大。求第K大可以用划分树,然后就二分一下K就好了。
#include <cstdio>
#include <algorithm>
using namespace std;
int sum[20][100005],node[20][100005],sorted[100005];
void build(int c,int s,int e)
{
int mid,lp,rp,lm,i;
mid=(s+e)>>1;
lm=0;
lp=s;
rp=mid+1;
for(i=s;i<=mid;i++) if(sorted[i]==sorted[mid]) lm++;
for(i=s;i<=e;i++)
{
if(s==i) sum[c][i]=0;
else sum[c][i]=sum[c][i-1];
if(node[c][i]==sorted[mid])
{
if(lm)
{
lm--;
sum[c][i]++;
node[c+1][lp++]=node[c][i];
}
else node[c+1][rp++]=node[c][i];
}
else if(node[c][i]<sorted[mid])
{
sum[c][i]++;
node[c+1][lp++]=node[c][i];
}
else node[c+1][rp++]=node[c][i];
}
if(s!=e)
{
build(c+1,s,mid);
build(c+1,mid+1,e);
}
}
int query(int c,int s,int e,int l,int r,int k)
{
if(s==e) return node[c][s];
else
{
int ls,rs,mid;
if(s==l)
{
ls=0;
rs=sum[c][r];
}
else
{
ls=sum[c][l-1];
rs=sum[c][r]-ls;
}
mid=(s+e)>>1;
if(rs>=k) return query(c+1,s,mid,s+ls,s+ls+rs-1,k);
else return query(c+1,mid+1,e,mid-s+1-ls+l,mid-s+1-ls-rs+r,k-rs);
}
}
int main()
{
int T,n,m,i,a,b,c,l,r,mid,ans,casenum;
scanf("%d",&T);
for(casenum=1;casenum<=T;casenum++)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d",&sorted[i]);
node[0][i]=sorted[i];
}
sort(sorted+1,sorted+n+1);
build(0,1,n);
printf("Case %d:\n",casenum);
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
if(query(0,1,n,a+1,b+1,1)>c)//特判
{
printf("0\n");
continue;
}
l=1,r=b-a+1;
while(l<=r)//二分
{
mid=(l+r)>>1;
if(query(0,1,n,a+1,b+1,mid)<=c)
{
ans=mid;
l=mid+1;
}
else
{
r=mid-1;
}
}
printf("%d\n",ans);
}
}
}
HDU-4417-Super Mario(划分树+二分),布布扣,bubuko.com
标签:des style blog http os 2014
原文地址:http://blog.csdn.net/faithdmc/article/details/37668709