第三次部落格總結
阿新 • • 發佈:2021-06-14
在補NOIonline
先隨手做一下這個T2的弱化版。
感覺這個就是T2的trick
\(tire\)樹認知不夠,數位思想差啊。
考慮用\(tire\)樹維護數集,然後高位往低位處理\(l\),如果\(l_i\)為\(1\),則和\(p_i\)相同一側子樹可以全部加入答案,再走和\(p_i\)不同一側遞迴下去,若\(l_i\)為0,則必須走\(p_i\)同側。
CF817E Choosing The Commander
#include<iostream> #include<cstdio> #define ll long long #define N 100005 ll n; int cnt; int ch[N * 16][2],s[N * 16]; inline void insert(ll c){ ll u = 0; for(int i = 30;i >= 0;--i){ if(!ch[u][(c >> i) & 1]) ch[u][(c >> i) & 1] = ++ cnt; s[u] ++ ; u = ch[u][(c >> i) & 1]; // std::cout<<u<<" "; } s[u] ++ ; // puts(""); } inline void del(ll c){ ll u = 0; for(int i = 30;i >= 0;--i){ s[u] -- ; u = ch[u][(c >> i) & 1]; } s[u] -- ; } ll pi,li,ans; inline void solve(ll u,ll dep){ if(dep == 0) return; if((li >> (dep - 1)) & 1){ ll x = (pi >> (dep - 1) & 1); // std::cout<<u<<" "<<1<<" "<<dep - 1<<" "<<x<<" "<<s[ch[u][x]]<<std::endl; if(ch[u][x]) ans += s[ch[u][x]]; if(ch[u][!x]) solve(ch[u][!x],dep - 1); } else{ ll x = (pi >> (dep - 1) & 1); // std::cout<<u<<" "<<0<<" "<<dep - 1<<" "<<x<<std::endl; if(ch[u][x]) solve(ch[u][x],dep - 1); } } int main(){ scanf("%lld",&n); while(n -- ){ ll opt; scanf("%lld",&opt); if(opt == 1){ ll p; scanf("%lld",&p); insert(p); } if(opt == 2){ ll p; scanf("%lld",&p); del(p); } if(opt == 3){ scanf("%lld%lld",&pi,&li); ans = 0; solve(0,31); std::cout<<ans<<std::endl; } } }
ps:最近程式碼能力提上了,不過還要注意對拍。
以及我還是沒搞懂\(tire\)要開多大空間,從這題上看,得開到\(16n\)(n字串數量)啊。
下回弄懂了,回來補坑。