BZOJ 2568 位元集合

2021-09-07 23:13:00 字數 1809 閱讀 3920

題意:維護乙個集合s,支援以下操作:

(1)ins m : 將元素 m 插入到集合s中;

(2)del m : 將集合s中所有等於 m 的元素刪除;

(3)add m : 將集合s中的所有元素都增加數值m ;

(4)qbit k : 查詢集合中有多少個元素滿足其二進位制的第 k位為 1 。

思路:(1) add 操作的那個和單獨拿出來,設為sum,集合s中的每個元素x實際值為x+sum;

(2)設f[k][t]表示第k位為1,且這個數字小於等於t的數字的個數。每次查詢時,設l=2^x,r=2^(x+1)-1,則答案為f[k][r]-f[k][l-1];

(3)由於增加乙個數字時這個f值是成段改變,因此要用樹狀陣列維護這個f陣列;

(4)對於那些插入的數字都是多少以及每個數字有多少個,用乙個map記錄,這樣刪除時就知道在樹狀陣列要減去多少。

我當時有個問題沒有明白,因為插入x時實際要插入的數字是x-sum,那麼x-sum為負數時這個位跟正數的位不太一樣。負數的二進位制表示是對應正數的二進位制表示取反加1。

比如-1=11111111 11111111  11111111 11111111 

-2=11111111 11111111  11111111 11111110

-3=11111111 11111111  11111111 11111101

-4=11111111 11111111  11111111 11111100

直接插入(下面可以看到,不需要特殊考慮負數)

後面那還加了個1是因為樹狀陣列裡下標都是從1開始的。

然後求和時是這樣的

這個分為兩部分,第一部分:計算的是[l,r]區間,設k=2,那麼二進位制表示l=100,r=111。設sum=1011,那麼實際要計算的區間為[001,100],只要乙個數字的後三位在這個區間,即[001,100],那麼它加上sum之後的後三位都會落到[l,r]區間。其實這個是沒有進製的。

我們再設sum=1110,其他不變,那麼上面的實際求和區間變成[000,001]。我們發現,除了這個區間,[110,111]這個區間也是可以的。這個其實是進製產生的,進製之後求和區間由[100,111]變為[1100,1111],這樣減去sum的後三位110實際區間為[110,1001],我們發現1001,1000都不會有這個值,所以實際就是[110,111]。這就是上面求和的第二部分。

那麼乙個負數加上sum之後也可能到達這個區間,sum=1110,[-10,-7],這些負數的二進位制為

-10=11111111 11111111  11111111 11110110 

-9  =11111111 11111111  11111111 11110111

-8  =11111111 11111111  11111111 11111000

-7  =11111111 11111111  11111111 11111001

我們發現,後三位都在計算的兩個區間裡。所以負數不需要額外考慮。

int s[20][n];

mapmp;

int n;

void add(int k,int x,int t)

int get(int k,int x)

int main()

else if('d'==op[0])

else if('q'==op[0])}}

bzoj2568 位元集合

位元集合是一種抽象資料型別 abstract data type 其包含乙個集合s,並支援如下幾種操作 ins m 將元素 m 插入到集合s中 del m 將集合s中所有等於 m 的元素刪除 add m 將集合s中的所有元素都增加數值m qbit k 查詢集合中有多少個元素滿足其二進位制的第 k位為...

BZOJ 2301 莫比烏斯

比較裸的一道莫比烏斯入門題 具體題解網上多的是 比較簡單 不知道為什麼別人 都那麼長 沒有我的優雅哈哈哈 這題不要列舉 要分塊處理 ac includeusing namespace std typedef long long ll const ll n 1e6 ll miu n 10 v n 10...

bzoj 2440 (莫比烏斯函式)

bzoj 2440 完全平方數 題意 找出第k個不是完全平方數的正整數倍的數。例如 4 9 16 25 36什麼的 通過容斥原理,我們減去所有完全數 4有n 4個,但是先36這種會被重複減去,所有我們還需要加上類似36的數,然後你會發現這些數前面的符號和他們開根號的 莫比烏斯函式一樣 資料很大有1e...