题解:P14507 缺零分治 mexdnc
贪心地想,我们每次都拿出来能拿出来的最大
我们维护
之后二分一下来看我们取了多少次,因为一个数出现次数可以很大,我们离散化一下就好了。
注意到有巨量边界情况,如果只需要取一次,但我们的询问并不是取一次取出来的最大值,我们需要再取一次把这两个值之间的数丢掉。为什么之前不需要丢掉这些数呢,其他情况在取第一次的时候全给取出来顺带丢掉就可以了。
考虑什么时候是无解,如果每次取最大取出来所有的数都到不了询问就无解,如果询问是零并且零的个数不为零无解。
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[110000],f[110000],s[110000],hn[110000],hcnt;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T;cin>>T;
while(T--){
int n,q;cin>>n>>q;hcnt=0;hn[++hcnt]=0;hn[++hcnt]=n+1;
for(int i=0;i<=n;i++) f[i]=n+1,a[i]=0,s[i]=0;
for(int i=1;i<=n;i++){
int x,y;cin>>x>>y;
if(x<=n) a[x]=y,hn[++hcnt]=y;
}
sort(hn+1,hn+hcnt+1);
int m=unique(hn+1,hn+hcnt+1)-hn-1;
for(int i=0;i<=n;i++) a[i]=lower_bound(hn+1,hn+m+1,a[i])-hn;
for(int i=0;i<=n;i++){
if(a[i]<m) f[a[i]]=min(f[a[i]],i);
}
for(int i=1;i<=m;i++) f[i]=min(f[i],f[i-1]);
s[1]=f[1]*(hn[2]-hn[1]);
for(int i=2;i<=m-1;i++) s[i]=s[i-1]+f[i]*(hn[i+1]-hn[i]);
while(q--){
int x;cin>>x;
if(x==0 and hn[a[0]]==0) cout<<"1\n";
else if(x==0 or x>s[m-1]) cout<<"-1\n";
else{
int ans=lower_bound(s+1,s+m,x)-s;
int t=(s[ans]-x)/f[ans];
if((hn[ans+1]-t==1) and (x!=f[ans])) t--;
cout<<hn[ans+1]-t<<'\n';
}
}
}
return 0;
}