cogs930
找第k小的数
输入文件:kth.in 输出文件:kth.out 简单对比
时间限制:1 s 内存限制:256 MiB
【题目描述】
看到很短的题目会让人心情愉悦,所以给出一个长度为N的序列A1,A2,A3,...,AN,
现在有M个询问,每个询问都是Ai...Aj中第k小的数等于多少。
【输入格式】
第一行两个正整数N,M。
第二行N个数,表示序列A1,A2,...,AN。
紧着的M行,每行三个正整数i,j,k(k≤j-i+1),表示
询问Ai...Aj中第k小的数等于多少。
【输出格式】
共输出M行,第i行输出第i个询问的答案。
【样例输入1】
4 3
4 1 2 3
1 3 1
2 4 3
1 4 4
【样例输出1】
1
3
4
【样例输入2】
5 5
4 2 9 9 10
1 3 1
2 4 3
1 4 4
3 5 2
2 5 2
【样例输出2】
2
9
9
9
9
【提示】
询问区间的第k小值并非严格第k小,例如样例2中第4个询问,询问3到5中第2小的数,
答案输出9,并不是严格第2小的10。
在50%的数据中,1<=N<=10,000,1<=M<=10,000,A[i]<=100,000;
在100%的数据中,1<=N<=100,000,1<=M<=100,000,A[i]<=1,000,000;
原本是要刷一个CDQ分支的题目,可是做不出来。后来看题解才知道是整体二分!也就学习了一下。
整体二分,简单来说,就是把多个询问进行一起二分答案!
比CDQ分治要难!
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
int n,m;
struct num
{
int p,x;
}a[maxn],a1[maxn],a2[maxn];
struct que
{
int l,r,k,id;
}q[maxm],q1[maxm],q2[maxm];
int sm[maxm];
void add(int pos,int x)
{
for(int i=pos;i<=1000000;i+=i&-i)sm[i]+=x;
}
int query(int pos)
{
int ret=0;
for(int i=pos;i;i-=i&-i)ret+=sm[i];
return ret;
}
int ans[maxn];
void solove(int l,int r,int al,int ar,int ql,int qr)
{
if(l>r||ql>qr||al>ar)return;
if(l==r)
{
for(int i=ql;i<=qr;++i)ans[q[i].id]=l;
return ;
}
int mid=(l+r)>>1;
int a1c=0,a2c=0;
for(int i=al;i<=ar;++i)
{
if(a[i].x<=mid)
{
add(a[i].p,1);a1[al+a1c]=a[i];a1c++;
}
else a2[al+a2c]=a[i],++a2c;
}
int q1c=0,q2c=0;
for(int i=ql;i<=qr;++i)
{
int tp=query(q[i].r)-query(q[i].l-1);
if(tp>=q[i].k)q1[ql+q1c]=q[i],++q1c;
else q[i].k-=tp,q2[ql+q2c]=q[i],++q2c;
}
for(int i=al;i<al+a1c;++i)a[i]=a1[i];
for(int i=al+a1c;i<=ar;++i)a[i]=a2[i-a1c];
for(int i=ql;i<ql+q1c;++i)q[i]=q1[i];
for(int i=ql+q1c;i<=qr;++i)q[i]=q2[i-q1c];
for(int i=al;i<al+a1c;++i)add(a1[i].p,-1);
solove(l,mid,al,al+a1c-1,ql,ql+q1c-1);
solove(mid+1,r,al+a1c,ar,ql+q1c,qr);
}
int mx=-1,mn=1000001;
int main()
{
freopen("kth.in","r",stdin);
freopen("kth.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i].x),a[i].p=i;
mx=max(mx,a[i].x);
mn=min(mn,a[i].x);
}
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
q[i].id=i;
}
solove(mn,mx,1,n,1,m);
for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
return 0;
}