Choosing The Commander CodeForces - 817E (01字典樹)
阿新 • • 發佈:2018-11-10
題意:給出三個操作,第一種操作是1 pi表示加入一個士兵的個性值為pi,第二種操作是2 pi表示撤離一個士兵的個性值為pi,第三種操作是3 pj lj,問加入的士兵中個性值與這個pj異或下來的值是否小於lj,在加入的士兵中總共有多少個這種士兵?
題解:首先存在大量的按位異或的運算,那麼可以把加入的士兵的個性值設為二進位制存入字典樹中,然後用val維護個數,這樣撤離也直接維護val即可,這樣查詢是如果此時這個位上的lj是0的話,把指標轉到相應pj的此時的位上,否則直接加上pj這個位上的數量,把指標轉到另一邊即可。
附上程式碼:
#include<bits/stdc++.h> using namespace std; const int maxnode=1e5*50; const int sigma_size=5; struct Trie{ int ch[maxnode][sigma_size]; int val[maxnode]; int sz; void clear(){ sz=1; memset(ch,0,sizeof(ch)); memset(val,0,sizeof(val)); } void insert(int x){ int u=0; for(int i=31;i>=0;i--){ int a=bool(x&(1<<i)); if(!ch[u][a]){ memset(ch[sz],0,sizeof(ch[sz])); ch[u][a]=sz++; } u=ch[u][a]; val[u]++; } } void deletee(int x){ int u=0; for(int i=31;i>=0;i--){ int a=bool(x&(1<<i)); u=ch[u][a]; val[u]--; } } int find_prefixes(int x,int l){ int u=0,ans=0; for(int i=31;i>=0;i--){ int tx=bool(x&(1<<i)); int tl=bool(l&(1<<i)); if(tl==0){ u=ch[u][tx]; }else{ ans+=val[ch[u][tx]]; u=ch[u][1-tx]; } if(u==0){ break; } } return ans; } }; Trie trie; int main() { int q; scanf("%d",&q); int com,p,l; trie.clear(); for(int i=1;i<=q;i++){ scanf("%d",&com); if(com==1){ scanf("%d",&p); trie.insert(p); }else if(com==2){ scanf("%d",&p); trie.deletee(p); }else{ scanf("%d%d",&p,&l); int ans=trie.find_prefixes(p,l); printf("%d\n",ans); } } return 0; }