离线做
先按照t[]建线段树,维护区间的有效天数以及可用时间
然后把t[]从小到达排序,记得记录t中元素在线段树中的位置
把询问按照d从小到大排序,依次考虑
由于按照d排序,所以当前询问肯定是d最短的,我们在t数组中找到大于当前d的第一个元素位置,把这之前的元素全部从线段树中删除,表示这些天数无效
因为当前d已经是最小,所以删除对后续不会有影响
二分一个天数,查找0~mid天一共的工作时间(工作时间=总可用时间-准备时间*有效天数)
#include"cstdio" #include"queue" #include"cmath" #include"stack" #include"iostream" #include"algorithm" #include"cstring" #include"queue" #include"map" #include"set" #include"vector" #define ll long long #define mems(a,b) memset(a,b,sizeof(a)) #define ls pos<<1 #define rs pos<<1|1 using namespace std; const int MAXN = 200500; const int MAXQ = 10050; const int INF = 0x3f3f3f3f; struct T{ ll w; int id; }t[MAXN]; struct Q{ int d,r,id; }q[MAXN]; struct Node{ int l,r; int now; ll sum; }node[MAXN<<2]; int ans[MAXN]; int n,m; bool cmp(Q a,Q b){ return a.d<b.d; } bool cmp1(T a,T b){ return a.w<b.w; } void pushup(int pos){ node[pos].sum=node[ls].sum+node[rs].sum; node[pos].now=node[ls].now+node[rs].now; } void build(int l,int r,int pos){ node[pos].l=l; node[pos].r=r; if(l==r){ node[pos].sum=t[l].w; node[pos].now=1; return; } int mid=(l+r)>>1; build(l,mid,ls); build(mid+1,r,rs); pushup(pos); } int get_pos(ll x){ int low=0,high=m-1,mid,ans=m; while(low<=high){ mid=(low+high)>>1; if(t[mid].w>x){ ans=mid; high=mid-1; } else low=mid+1; } return ans; } void del(int p,int pos){ if(node[pos].l==p&&node[pos].r==p){ node[pos].sum=0; node[pos].now=0; return; } int mid=(node[pos].l+node[pos].r)>>1; if(p<=mid) del(p,ls); else del(p,rs); pushup(pos); } ll query(int l,int r,int pos,int D){ ll ans=0; if(l<=node[pos].l&&node[pos].r<=r){ return node[pos].sum-(ll)node[pos].now*D; } int mid=(node[pos].r+node[pos].l)>>1; if(l<=mid) ans+=query(l,r,ls,D); if(r>mid) ans+=query(l,r,rs,D); return ans; } int main(){ scanf("%d%d",&n,&m); for(int i=0;i<m;i++){ scanf("%I64d",&t[i].w); t[i].id=i; } build(0,m-1,1); sort(t,t+m,cmp1); for(int i=0;i<n;i++){ scanf("%d%d",&q[i].d,&q[i].r); q[i].id=i; } sort(q,q+n,cmp); int j=0; for(int i=0;i<n;i++){ int pos=get_pos((ll)q[i].d); for(;j<pos;j++) del(t[j].id,1); if(node[1].sum-q[i].d*node[1].now<q[i].r){ ans[q[i].id]=0; continue; } int low=0,high=m-1,mid,t; while(low<=high){ mid=(low+high)>>1; ll a=query(0,mid,1,q[i].d); if(a>=q[i].r){ t=mid+1; high=mid-1; } else low=mid+1; } ans[q[i].id]=t; } for(int i=0;i<n;i++) printf("%d ",ans[i]); return 0; }