题意:
给一个数列。定义一种操作如下:令mid为现数列中 (最大值+最小值)/2 向下取整,将数列分为两部分,左半边为所有不超过mid的数,右半边为所有超过mid的数,选择一部分,并将令一部分删去。给若干次询问,每次问能否经过若干次(包括 0次)操作,使得最后的数列和为给定数值。
用set维护这个东西,按他的题意走
#include<bits/stdc++.h> #define inf 0x3f3f3f3f #define ll long long using namespace std; const int N=1e5+7; ll a[N],s[N],n,m,q; set<ll> v; void did(ll l,ll r){ v.insert(s[r]-s[l-1]); ll mid=a[l]+a[r]>>1; if(mid>=a[r]||mid<a[l]) return;//重复区间不下探 ll midpos=upper_bound(a+l,a+r+1,mid)-a-1;//找第一个大于mid的位置,减去一 did(l,midpos);//划分两边 did(midpos+1,r); } int main(){ int t;cin>>t; while(t--){ v.clear(); scanf("%lld%lld",&n,&m); for(int i=1;i<=n;++i){ scanf("%lld",&a[i]); } sort(a+1,a+n+1); for(int i=1;i<=n;++i){ s[i]=s[i-1]+a[i]; } did(1,n); while(m--){ scanf("%lld",&q); if(v.count(q))printf("Yes "); else printf("No "); } } return 0; }