题目大意:
思路:
直接模拟这个二分的过程,然后标记查询区间元素总和,用map标记。dfs进行二分模拟的上界是a[]的最大值,下界是a[]的最小值。用树状数组储存答案,查询区间内元素总和。对于dfs模拟中要判断mid是否存在于a[]中,如果不存在就需要再二分找到最接近mid的。(a[]从小到大排序)把所有可以得到的答案都用map标记后,再进行后面的查询,直接输出答案。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+50;
typedef long long ll;
ll T,n,m,a[maxn],sum[maxn],minn,maxx;
map<ll,int>mp;
ll lowbit(ll x){
return x&(-x);
}
ll query(ll x){
ll res=0;
while(x){
res+=sum[x];
x-=lowbit(x);
}
return res;
}
void add(ll x,ll w){
while(x<=maxx){
sum[x]+=w;
x+=lowbit(x);
}
}
void dfs(ll l,ll r){
mp[query(r)-query(l-1)]=1;
if(l>=r)return ;
ll mid=(l+r)/2;
ll t1=lower_bound(a+1,a+1+n,mid)-a;
ll t2=lower_bound(a+1,a+1+n,mid+1)-a;
ll midl,midr;
if(a[t1]==mid)midl=mid;
else midl=a[t1-1];
midr=a[t2];
dfs(l,midl);dfs(midr,r);
}
int main(){
cin>>T;
while(T--){
cin>>n>>m;
maxx=0;minn=1e18;
for(int i=1;i<=n;i++)cin>>a[i],maxx=max(maxx,a[i]),minn=min(minn,a[i]);
sort(a+1,a+1+n);
for(int i=0;i<=maxx;i++)sum[i]=0;
for(int i=1;i<=n;i++){
add(a[i],a[i]);
}
mp.clear();
dfs(minn,maxx);
while(m--){
ll x;cin>>x;
if(mp[x])cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
return 0;
}