用线段树维护满足条件序号最小的那个
代码如下
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+7;
const int inf=1e9;
int ans1[maxn],ans2[maxn],n,m,a[maxn],mi[maxn*4],q,d;
int cnt=0,res=0;
void Build(int o,int l,int r)
{
if(l==r) {
mi[o]=a[l];
return ;
}
int mid=l+r>>1;
Build(o<<1,l,mid);
Build(o<<1|1,mid+1,r);
mi[o]=min(mi[o<<1],mi[o<<1|1]);
}
void Update(int o,int l,int r,int pos)
{
if(l==r) {
mi[o]=inf;
return ;
}
int mid=l+r>>1;
if(mid>=pos) {
Update(o<<1,l,mid,pos);
}
else {
Update(o<<1|1,mid+1,r,pos);
}
mi[o]=min(mi[o<<1],mi[o<<1|1]);
}
int Query(int o,int l,int r)
{
if(mi[o]>res) {
return -1;
}
if(l==r) {
return l;
}
int mid=l+r>>1;
if(mi[o<<1]<=res) {
return Query(o<<1,l,mid);
}
else if(mi[o<<1|1]<=res){
return Query(o<<1|1,mid+1,r);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
}
Build(1,1,n);
for(int i=1;i<=maxn;i++) {
if(cnt==n) {
ans1[i]=cnt;
ans2[i]=res;
continue;
}
res+=m;
while(1) {
int pos=Query(1,1,n);
if(pos==-1) {
break;
}
res-=a[pos];
cnt++;
Update(1,1,n,pos);
}
ans1[i]=cnt;
ans2[i]=res;
}
scanf("%d",&q);
while(q--) {
scanf("%d",&d);
printf("%d %d\n",ans1[d],ans2[d]);
}
}