在這個問題中,最初會給你一個空的多集。您必須處理兩種類型的查詢:
ADD x x x - 在多集合中添加一個等于 2 x 2x 2x 的元素;
GET w w w - 詢問是否可以求當前多集的某個子集的和,并得到等于 w w w 的值。
輸入
第一行包含一個整數 m ( 1 ≤ m ≤ 1 0 5 ) m ( 1≤m≤10^5 ) m(1≤m≤105) - 查詢次數。
然后是 m m m 行,每行包含兩個整數 t i 、 v i t_i 、 v_i ti?、vi? ,表示 i i i 次查詢。如果是 t i = 1 t_i=1 ti?=1 ,那么 i i i 次查詢就是 ADD v i ( 0 ≤ v i ≤ 29 ) v_i ( 0≤v_i≤29 ) vi?(0≤vi?≤29).如果是 t i = 2 t_i=2 ti?=2 ,那么 i i i 這條查詢就是 GET v i ( 0 ≤ v i ≤ 1 0 9 ) v_i ( 0≤v_i≤10^9 ) vi?(0≤vi?≤109)。
輸出
對于每個 GET 查詢,如果可以選擇總和等于 w w w 的子集,則打印 YES
;如果不可能,則打印 NO
。
雖然本題標上了Bitsmasks的標簽,但是其實考查的是貪心。
首先明確貪心策略,如果我們想要用一堆2的某次方來表示出一個數,那么我們應該盡可能多的用大數。
怎么會如此 ?😃😃😃😃
因為小數能夠表示的狀態肯定會比大數多,例如如果你有無窮多的 1 1 1,那么你就能夠表示各種數字,因為任意數字都可以拆分成多個 1 1 1,但是如果你有很多個 w w w,那你怎么也表示不了 9999 9999 9999。
也就是說如果保證小數最多的情況下這個數還是無法被表示出來的話,那么就肯定沒有可能表示出來了。
(水平有限無法給出嚴謹數學證明)
CODE:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int st[30];signed main(){int m;cin >> m;while(m--){int t,v;cin >> t >> v;if(t == 1){st[v]++;}else{for(int i = 29;i >= 0;i--){int l = 0,r = st[i];while(l < r){int mid = l + r + 1 >> 1;if(mid * (1 << i) <= v)l = mid;else r = mid - 1;}v -= r *(1 << i);}if(!v)cout << "YES\n";else cout << "NO\n";}}return 0;
}