//hdu 2665 这里就做为划分树模板了;
#include<stdio.h>
#include<algorithm>
using namespace std;
#define N 100100
int data[N];
struct node
{
int v[N];
int num[N];
}td[31];
void build(int l,int r,int dep)
{
if(l>=r)return;
int i,mid=(l+r)>>1,midd=data[mid],ant=mid-l+1;
int ln=l-1,rn=mid;
for(i=l;i<=r;i++)
if(td[dep].v[i]<midd)
ant--;
for(i=l;i<=r;i++)
{
if(i==l)
td[dep].num[i]=0;
else
td[dep].num[i]=td[dep].num[i-1];
if(td[dep].v[i]<midd||(td[dep].v[i]==midd&&ant))
{
if(td[dep].v[i]==midd)--ant;
td[dep+1].v[++ln]=td[dep].v[i];
++td[dep].num[i];
}
else td[dep+1].v[++rn]=td[dep].v[i];
}
build(l,mid,dep+1);
build(mid+1,r,dep+1);
}
int query(int a,int b,int k,int l,int r,int dep)
{
int mid=(l+r)>>1;
if(a==b)return td[dep].v[a];
int lx,rx=td[dep].num[b],sub,sl,sr;
lx=(a<=l)?0:td[dep].num[a-1];
sub=rx-lx;
if(sub>=k)
return query(l+lx,l+rx-1,k,l,mid,dep+1);
else
{
sl=a-l-lx;
sr=b-l-rx;
return query(mid+1+sl,mid+1+sr,k-sub,mid+1,r,dep+1);
}
}
int main()
{
int i,cas,n,m,l,r,k;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d",&td[1].v[i]);
data[i]=td[1].v[i];
}
sort(data+1,data+n+1);
build(1,n,1);
while(m--)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",query(l,r,k,1,n,1));
}
}
return 0;
}
/*
//
csu 1080(力所能及)
csu 上的一道划分树求前k大的和的题;
划分树的关键在于的它的划分,以及它的那个记录当前点前面有多少被划分到左子树的辅助数组,真的很巧妙;
这道题还需要一个sum数组来辅助计算;
*/
#include<stdio.h>
#include<algorithm>
using namespace std;
#define N 10100
struct nd
{
int dul;
int v;
}data[N];
struct node
{
nd v[N];
int num[N];
int sum[N];
}td[31];
int pre[N];
bool cmp(nd a,nd b){return a.dul<b.dul;}
bool cmp_(nd a,nd b){return a.v>b.v;}
void build(int l,int r,int dep)
{
if(l>=r)return;
int i,mid=(l+r)>>1,midd=data[mid].v,ant=mid-l+1;
int ln=l-1,rn=mid;
for(i=l;i<=r;i++)
if(td[dep].v[i].v>midd)
ant--;
for(i=l;i<=r;i++)
{
if(i==l)
td[dep].num[i]=td[dep+1].sum[ln+1]=td[dep+1].sum[rn+1]=0;
else
td[dep].num[i]=td[dep].num[i-1];
if(td[dep].v[i].v>midd||(td[dep].v[i].v==midd&&ant))
{
if(td[dep].v[i].v==midd)--ant;
td[dep+1].v[++ln].v=td[dep].v[i].v;
if(ln!=l)
td[dep+1].sum[ln]=td[dep+1].sum[ln-1];
td[dep+1].sum[ln]+=td[dep].v[i].v;
++td[dep].num[i];
}
else{
td[dep+1].v[++rn].v=td[dep].v[i].v;
if(rn!=mid+1)
td[dep+1].sum[rn]=td[dep+1].sum[rn-1];
td[dep+1].sum[rn]+=td[dep].v[i].v;
}
}
build(l,mid,dep+1);
build(mid+1,r,dep+1);
}
int query(int a,int b,int k,int l,int r,int dep)
{
int mid=(l+r)>>1,ans,yy;
if(a==b)return td[dep].v[a].v;
int lx,rx=td[dep].num[b],sub,sl,sr;
lx=(a<=l)?0:td[dep].num[a-1];
sub=rx-lx;
if(sub>=k)
return query(l+lx,l+rx-1,k,l,mid,dep+1);
else
{
sl=a-l-lx;
sr=b-l-rx;
ans=(lx==0)?0:td[dep+1].sum[l+lx-1];
yy=(rx==0)?0:td[dep+1].sum[l+rx-1];
return yy-ans+query(mid+1+sl,mid+1+sr,k-sub,mid+1,r,dep+1);
}
}
int find(int v,int n,int flag)
{
int start=0,end=n+1,mid;
while(1)
{
mid=(start+end)>>1;
if(start==mid)break;
if(flag)
{
if(td[1].v[mid].dul<v)
start=mid;
else end=mid;
}
else
{
if(td[1].v[mid].dul>v)
end=mid;
else start=mid;
}
}
return start+flag;
}
int main()
{
int n,i,cnt,m,l,r,k;
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
while(scanf("%d",&n)!=EOF)
{
for(i=1,cnt=0;i<=n;i++){
++cnt;
scanf("%d%d",&data[cnt].dul,&data[cnt].v);
if(data[cnt].v<=0)
cnt--;
}
if(cnt>0){
sort(data+1,data+cnt+1,cmp);
for(i=1,pre[0]=0;i<=cnt;i++){
pre[i]=pre[i-1]+data[i].v;
td[1].v[i].v=data[i].v;
td[1].v[i].dul=data[i].dul;
}
sort(data+1,data+cnt+1,cmp_);
build(1,cnt,1);
}
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d",&l,&r,&k);
if(cnt<1)
{
printf("0\n");
continue;
}
l=find(l,cnt,1);
r=find(r,cnt,0);
if(l>cnt||l>r)
{
printf("0\n");
continue;
}
if(k>r-l+1)
printf("%d\n",pre[r]-pre[l-1]);
else
printf("%d\n",query(l,r,k,1,cnt,1));
}
printf("\n");
}
return 0;
}
//csu1080 主席树版代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 10010
#define FN 200010
int C[FN],L[FN],R[FN],sum[FN],T[N],tot,cnt;
int build(int l,int r)
{
int mid=(l+r)>>1,rt=++tot;
if(l==r) return rt;
L[rt]=build(l,mid);
R[rt]=build(mid+1,r);
return rt;
}
int update(int rt,int p,int d,int v)
{
int newrt=++tot,root=newrt;
int l=1,r=cnt,mid;
C[newrt]=C[rt]+d; sum[newrt]=sum[rt]+v;
while(l<r)
{
mid=(l+r)>>1;
if(p<=mid)
{
L[newrt]=++tot; R[newrt]=R[rt];
newrt=L[newrt]; rt=L[rt];r=mid;
}
else
{
R[newrt]=++tot;L[newrt]=L[rt];
newrt=R[newrt];rt=R[rt];l=mid+1;
}
C[newrt]=C[rt]+d;sum[newrt]=sum[rt]+v;
}
return root;
}
int query(int rt1,int rt2,int k)
{
int l=1,r=cnt,mid,ans=0;
while(l<r)
{
mid=(l+r)>>1;
if(C[L[rt2]]-C[L[rt1]]>=k)
rt2=L[rt2],rt1=L[rt1],r=mid;
else{
ans+=sum[L[rt2]]-sum[L[rt1]];
k-=C[L[rt2]]-C[L[rt1]];
rt1=R[rt1];rt2=R[rt2];l=mid+1;
}
}
return ans+sum[rt2]-sum[rt1];
}
struct node { int dul,v,sd; }data[N];
bool cmp1(node a,node b){ return a.v>b.v; }
bool cmp2(node a,node b){ return a.dul<b.dul; }
int find(int v,int n,int flag)
{
int start=0,end=n+1,mid;
while(1)
{
mid=(start+end)>>1;
if(start==mid)break;
if(flag)
{
if(data[mid].dul<v) start=mid;
else end=mid;
}
else
{
if(data[mid].dul>v) end=mid;
else start=mid;
}
}
return start+flag;
}
int p[N];
int main()
{
int i,m,k,a,b,n;
while(scanf("%d",&n)!=EOF)
{
tot=cnt=0;
for(i=1;i<=n;i++)
{
++cnt;
scanf("%d%d",&data[cnt].dul,&data[cnt].v);
if(data[cnt].v<=0) --cnt;
}
if(cnt){
sort(data+1,data+cnt+1,cmp1);
for(i=1;i<=cnt;i++)
data[i].sd=i;
sort(data+1,data+cnt+1,cmp2);
for(i=1;i<=cnt;i++) p[i]=p[i-1]+data[i].v;
T[0]=build(1,cnt);
for(i=1;i<=cnt;i++)
T[i]=update(T[i-1],data[i].sd,1,data[i].v);
}
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d",&a,&b,&k);
if(cnt<1)
{
printf("0\n");
continue;
}
a=find(a,cnt,1);
b=find(b,cnt,0);
if(a>cnt||a>b)
{
printf("0\n");
continue;
}
if(k>=b-a+1) printf("%d\n",p[b]-p[a-1]);
else printf("%d\n",query(T[a-1],T[b],k));
}
printf("\n");
}
return 0;
}