G - Vitya and Strange Lesson(字典樹 )
阿新 • • 發佈:2018-11-04
G - Vitya and Strange Lesson
題意:給你一個數組,讓數組裡面的值都異或一下x,並構成一個新的陣列,求這個陣列的mex
mex的含義:不在陣列中的最小正整數。
思路:
異或的交換律
1.首先我們知道,異或x之後得到的陣列將其再異或y值得到的陣列,其實就是原陣列異或(x^y)的結果。所以這裡我們沒有必要將原陣列進行變化。
異或的唯一性即 a^b=c 如果b,c確定則a就確定
2.我們將原陣列中不存在的數入樹。那麼對於每一個查詢temp,其實就相當於我們在樹上找一個值,使得這個值亦或temp最小。(如果此處不懂,請看最後面)
3.找出異或最小值即可
**那麼這個數的範圍怎麼確定呢?**題中所有資料的範圍都在0~3e5之間,即二進位制第25位之前的全為0,
所以陣列中的數與x異或後的數也都滿足第二進位制第25位之前的全為0,那麼所求的mex的二進位制的第25位之前也全為0,a^b=c b c滿足這樣,所以a的進位制的第25位之前也全為0,
即要求原陣列中不存在的數的範圍最下為2^25即可(這樣的1~25位的的二進位制所有情況全部列舉,答案肯定是與其中一個異或)
#include<iostream> #include<string.h> #include<string> #include<stdio.h> #include<cstdlib> #include<algorithm> #include<vector> using namespace std; const int maxn=10000010; const int maxval=524288; int ans[40]; int book[maxval]; struct Node{ int net[2]; Node() { clear(); } void clear() { net[0]=net[1]=-1; } }node[maxn]; int top; void clear_tree(int &top)//清空樹 { for(int i=0;i<=top;++i) node[i].clear(); top=0; } int Getbit(int &val,int k)//val的第k位是多少 { if(val&(1<<(k-1))) return 1; return 0; } void Becomebit(int &val,int k,int BitVal)//將val的第k位變為BitVal { if(BitVal) val=val|(1<<(k-1)); else val=val&(~(1<<(k-1))); } void insert_node(int &val)//將val的二進位制位從高到低插入進字典樹內 { int now=0; for(int i=32;i;--i) { if(node[now].net[Getbit(val,i)]==-1) node[now].net[Getbit(val,i)]=++top; now=node[now].net[Getbit(val,i)]; } } int dfs(int now,int bit,int k)//根據當前節點和位數返回下一個節點 並且記下選的位數 { if(~node[now].net[bit]) { ans[k]=bit; return node[now].net[bit]; } ans[k]=bit?0:1; return node[now].net[bit?0:1]; } int Solve(int &val)//x的值不能改變 { int now=0; for(int i=32;i;--i) { now=dfs(now,Getbit(val,i),i);//this? } int res; for(int i=32;i;--i) Becomebit(res,i,ans[i]); return res; } int main() { int x,n,m; scanf("%d %d",&n,&m); memset(book,0,sizeof(book)); for(int i=0;i<n;++i) { int mid; scanf("%d",&mid); book[mid]=1; } x=0; for(int i=0;i<=maxval;++i) if(!book[i]) insert_node(i);//this? while(m--) { int mid; scanf("%d",&mid); x^=mid; printf("%d\n",x^Solve(x)); } }
參考部落格 https://blog.csdn.net/mengxiang000000/article/details/77718605
為什麼與原陣列異或x後的陣列的mex是不在原陣列中的數與x異或的最小值?
假設現在陣列a與x異或得到陣列c 那麼因為異或的唯一性,不在陣列c的值構成的集合即為不在陣列a的值與x異或構成的集合,(因為在陣列a的值與x異或一定在陣列c中)