和二叉树的遍历形式差不多,往左右两棵子树不断递归。
不过这道题要在往下递归的途中不断进行找中间数以及求和。
另外可以用map来保存一个值是否出现过。
#include <iostream> #include <algorithm> #include <map> using namespace std; typedef long long LL; const int N = 1e5 + 10; map<LL, int> mp; LL n, m, a[N], sum[N]; void solve(int l, int r){ if(l < 1 || r > n || l > r) return; if(a[l] == a[r]){ mp[a[l] * (r - l + 1)] = 1; return; } LL mid = a[l] + a[r] >> 1; LL pos = upper_bound(a + l, a + r + 1, mid) - a - 1; if(pos) mp[sum[pos] - sum[l - 1]] = 1; mp[sum[r] - sum[pos]] = 1; solve(l, pos); solve(pos + 1, r); } int main(){ int t; cin >> t; while(t --){ mp.clear(); cin >> n >> m; for(int i = 1; i <= n; i ++) cin >> a[i]; sort(a + 1, a + 1 + n); for(int i = 1; i <= n; i ++) sum[i] = sum[i - 1] + a[i]; solve(1, n); mp[sum[n]] = 1; while(m --){ LL temp; cin >> temp; if(mp[temp] == 1) cout << "Yes" << endl; else cout << "No" << endl; } } return 0; }