Time Limit: 6000MS | Memory Limit: 65536K | |
Total Submissions: 8160 | Accepted: 2218 |
Description
Input
Output
Sample Input
7 2 1 5 2 6 3 7 4 1 5 3 2 7 1
Sample Output
3 2
http://blog.sina.com.cn/s/blog_5f5353cc0100ki2e.html
#include
#include
#include
#include
using namespace std;
const int N=101000;
const int DEEP=20;//划分树最多层数
struct Node
{
int l,r;
};
Node tree[N*4];//线段树
int data[N];//数据
int seg[DEEP][N];//划分树
int LessMid[DEEP][N];//表示在[L,R]内有几个数小于等于date[mid]
void buildtree(int root,int l,int r,int d)//节点,左右区间,层数
{
tree[root].l=l,tree[root].r=r;
if(l==r) return ;//叶子节点
int mid=(l+r)>>1;
int lsame=mid-l+1;//左面最多可放几个与data[mid]相同的数
for(int i=l;i<=r;i++)//得出实际能放几个相同的数
{
if(seg[d][i] }
int tl=l,tr=mid+1,same=0;//划分树 ,tl,tr表示数的左右子树的起点
for(int i=l;i<=r;i++)
{
if(i==l) LessMid[d][i]=0;//表示在[L,R]内有几个数小于等于date[mid]
else LessMid[d][i]=LessMid[d][i-1];
if(seg[d][i] else if(seg[d][i]>data[mid]) seg[d+1][tr++]=seg[d][i];//划分到右子树
else //相等情况
{
if(sameelse seg[d+1][tr++]=seg[d][i];
}
}
buildtree(root<<1,l,mid,d+1);
buildtree((root<<1)+1,mid+1,r,d+1);
}
//查询[l,r]中的第k小数
int Query(int root,int l,int r,int d,int cnt)//节点,要查询的区间,层数,第cnt小数
{
if(l==r) return seg[d][l];
int s;//表示在[l,r]中有几个小于等于data[mid]的个数
int ss;//表示在[tree[root].l,l-1]中有几个小于等于data[mid]的个数
if(l==tree[root].l) s=LessMid[d][r],ss=0;
else s=LessMid[d][r]-LessMid[d][l-1],ss=LessMid[d][l-1];
if(s>=cnt) return Query(root<<1,tree[root].l+ss,tree[root].l+ss+s-1,d+1,cnt);
else
{
int mid=(tree[root].l+tree[root].r)>>1;
int bb=l-tree[root].l-ss;//表示[tree[root].l,l-1]中有多少个分到右面
int b=r-l+1-s;//表示[l,r]有多少个分到右面
return Query((root<<1)+1,mid+bb+1,mid+bb+b,d+1,cnt-s);
}
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)==2)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&data[i]);
seg[1][i]=data[i];//划分树第一层
}
sort(data+1,data+1+n);
buildtree(1,1,n,1);
while(m--)
{
int l,r,k;scanf("%d%d%d",&l,&r,&k);
int res=Query(1,l,r,1,k);//查询[l,r]中的第k小数
printf("%d/n",res);
}
}
return 0;
}