划分树模板题,第一次写,昨天晚上琢磨了一晚上把思路理清楚,早上起来Wrong了之后,检查出一个下标错误,险险的A掉了。
ACcode:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int NS=100010;
struct node{
int num[NS];
int val[NS];
}row[18];
LL tot;
int n,m;
int st[NS];
void build(int dep,int L,int R)
{
if (L==R) return ;
int mid=(L+R)>>1;
int same=mid-L+1;
int idl=L,idr=mid+1;
for (int i=L;i<=R;i++)
if (row[dep].val[i]<st[mid]) same--;
for (int i=L;i<=R;i++)
{
if (i==L)
row[dep].num[i]=0;
else
row[dep].num[i]=row[dep].num[i-1];
if (row[dep].val[i]<st[mid]) {
row[dep].num[i]++;
row[dep+1].val[idl++]=row[dep].val[i];
} else if (row[dep].val[i]>st[mid]) {
row[dep+1].val[idr++]=row[dep].val[i];
} else {
if (same>0){
same--;
row[dep].num[i]++;
row[dep+1].val[idl++]=row[dep].val[i];
} else {
row[dep+1].val[idr++]=row[dep].val[i];
}
}
}
build(dep+1,L,mid);
build(dep+1,mid+1,R);
}
int query(int dep,int k,int x,int y,int L,int R)
{
if (L==R) return row[dep].val[L];
int a,b,ctl,ctm,sxy;
int mid=(L+R)>>1;
if (x==L)
ctl=0;
else
ctl=row[dep].num[x-1];
ctm=row[dep].num[y]-ctl;
if (ctm>=k) {
a=L+ctl;
b=a+ctm-1;
R=mid;
} else {
a=mid+1+(x-L-ctl);
b=a+(y-x+1-ctm)-1;
L=mid+1;
k-=ctm;
}
return query(dep+1,k,a,b,L,R);
}
int main()
{
int x,y,k;
while (~scanf("%d %d",&n,&m))
{
for (int i=1;i<=n;i++)
{
scanf("%d",&st[i]);
row[0].val[i]=st[i];
}
sort(st+1,st+n+1);
build(0,1,n);
while (m--)
{
scanf("%d %d %d",&x,&y,&k),tot=0;
printf("%d\n",query(0,k,x,y,1,n));
}
}
return 0;
}