hash 懶標記 記憶數字

2021-06-21 18:41:56 字數 2000 閱讀 7112

time limit: 5 sec  

memory limit: 256 mb

submit: 159  

solved: 17 [

submit][

status][

web board]

wanghang最近研製出了乙個機械人,這個機械人有乙個跨時代的功能:記憶數字!

這個機械人接受三種指令

第一種指令,記憶一系列數字

第二種指令,詢問乙個數字是否在機械人的記憶中

第三種指令,讓這個機械人忘記所有數字

第一行乙個正整數t<=10代表輸入資料個數

第二行乙個正整數n<=100000代表指令個數

然後n行,每行代表乙個指令,指令格式如下:

1 x k代表記憶k個數字x,x+2,x+4 ... x+2k-2 (1<=k<=50)

2 y 代表詢問y是否在機械人的記憶中

3 代表讓機械人忘記所有數字

對於每個第二種指令,輸出yes代表詢問的數字在機械人的記憶中,反之輸出no

151 1 52 22 332 2

noyesno

srssyd

考慮用hash表,插入和查詢接近o(1),clear操作是o(n)。十萬次查詢,每次查詢最多同時有五十萬個節點需要清空,時間開銷太大。如何解決clear的效率問題?

解決辦法是lazy標記,僅當使用到時才清零。具體實現是用乙個時間戳,再記錄每個鍊錶的版本號,一比較就知道是否需要更新。

感覺挺像可持久化程式設計的,其實不是。目的並不是要保留歷史版本。而是通過標記需要清空的元素,不到使用的時候就不對他進行清空,於是我們的清零的時間全部分散到了插入和查詢中。而對時間戳的更新只是o(1)的演算法。插入和查詢和原來的時間複雜度保持不變。因此這種lazy標記的思路就是乙個極好的優化。

注意,我們需要清零的是head陣列,因此每乙個煉表裡所有的元素都具有相同的時間戳,所以不應該對每個元素維護乙個時間戳,這樣對時間的優化是較小的

求hash值的時候,不要用abs。而對之and上0x7fffffff,直接捨掉符號位。這樣會使hash值分散得多,因為正負值的hash差異很大。

提交時一直re,原因是多組資料沒有的hash表clear。導致記憶體池的指標一直往後移,超過了預期的最大值maxn*maxk。

#include #include #include #include #include #include const double eps = 1e-6;

const int inf = 0x3f3f3f3f;

const int maxnk = 5000005;

int getint()

do res = (res << 1) + (res << 3) + tmp - '0';

while (isdigit(tmp = getchar()));

return sgn ? res : -res;

}struct node

node(){}

};const int mod = 13131313;

struct hashtable

bool find(int v)

for (int i=head[_hash];i;i=pool[i].next)

return false;

} void insert(int v)

for (int i=head[_hash];i;i=pool[i].next)

}if (!ok)

}void clear() };

hashtable table;

int main()

{ int t = getint();

while (t--)

{ table.clear();

int n = getint();

while (n--)

{ int o = getint();

if (o == 1)

{int x = getint();

int k = getint();

for (int i=0;i

線段樹(含懶標記)模板

理解分析 鏈結 include using namespace std typedef long long ll int n,m,a,b,x,y,p,ans struct nodetree 400005 void build int k,int ll,int rr int mid ll rr 2 b...

Hash 統計數字

給定n個數,每個數均不超過1.5 109,統計這些數各自出現的次數,並按照從小到大的順序輸出統計結果。資料規模有1.5 109,所以雜湊關鍵字本身作為位址會爆 所以想到用雜湊表 除了記錄某個s是否出現,還要記錄出現的次數,所以可以用乙個二維陣列,加乙個儲存出現次數的即可。完後,將雜湊表裡的數放在乙個...

codeforces (數字dp 記憶化搜尋)

題意 列舉 a,b 之間的beautiful數 即這個數所有位上的數都能整除這個數 思路 用pos記錄位置 num記錄當前位置前面所有位組成的數 當時開不了這麼大的陣列 有知道1 9 的最小公倍數是2520 所以num記錄 上文的num 2520 就可以了 現在就剩下記錄當前位置前面各位都出現過0 ...