【CF706D】Vasiliy's Multiset Trie+貪心
阿新 • • 發佈:2018-12-19
題目大意:需要維護一種資料結構,支援以下三種操作:插入一個數,刪除一個數,查詢該資料結構中的數異或給定數的最大值。
題解:如果沒有刪除操作就是一個標準的 Trie 上貪心求最大異或和問題。現在需要支援刪除操作,因此,在樹上每個節點維護一個額外的標記,表示有多少個數的某一位經過當前節點。插入操作依然只需修改樹上一條鏈,而刪除一個數時,同樣需要將這條鏈上的標記值減 1 即可。這時便可以根據經過的每個點標記值是否為 0 進行貪心操作。
程式碼如下
#include <bits/stdc++.h> using namespace std; const int maxn=2e5+1; int trie[maxn<<5][2],tot=1,tag[maxn<<5]; int q,x; void modify(int now,int idx,int val){ if(idx<0)return; int ch=x>>idx&1; if(!trie[now][ch])trie[now][ch]=++tot; now=trie[now][ch],tag[now]+=val; modify(now,idx-1,val); } int query(int now,int idx,int ans){ if(idx<0)return ans; int ch=x>>idx&1; if(tag[trie[now][ch^1]])now=trie[now][ch^1],ans|=1<<idx; else now=trie[now][ch]; return query(now,idx-1,ans); } void solve(){ char op[2]; modify(1,31,1); while(q--){ scanf("%s%d",op,&x); if(op[0]=='+')modify(1,31,1); else if(op[0]=='-')modify(1,31,-1); else printf("%d\n",query(1,31,0)); } } int main(){ scanf("%d",&q); solve(); return 0; }