HDU 4825 Xor Sum (模板題)【01字典樹】
阿新 • • 發佈:2019-03-02
spa namespace 給定 鏈接 targe printf 模板題 16px i++
<題目鏈接>
題目大意:
給定n個數,進行m次查找,每次查找輸出n個數中與給定數異或結果最大的數。
解題分析:
01字典樹模板題,01字典樹在求解異或問題上十分高效。利用給定數據的二進制數進行建樹,然後在查找的時候,利用貪心的策略,優先尋找與當前位數的0、1值不同的路線,從而達到異或值最大的目的。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5+5; int n,m,pos; ll val[N*32],nxt[N*32][2];void init(){ pos=1; memset(nxt,0,sizeof(nxt)); memset(val,0,sizeof(val)); } void Insert(ll x){ //用x的二進制建樹 int now=1; for(int i=32;i>=0;i--){ int to=(x>>i)&1; //從最高位開始建 if(!nxt[now][to])nxt[now][to]=++pos; now=nxt[now][to]; } val[now]=x; //標記前綴二進制串為完整的數字 } ll query(ll x){ //尋找01Trie樹上異或的最大數 int now=1; for(int i=32;i>=0;i--){ int to=(x>>i)&1; if(nxt[now][to^1])now=nxt[now][to^1]; //優先找與當前位不同的路線 else now=nxt[now][to]; //如果沒有的話,只能找相同的 } return val[now]; } int main(){int ncase=0; int T;scanf("%d",&T);while(T--){ init(); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ ll cur;scanf("%lld",&cur); Insert(cur); } printf("Case #%d:\n",++ncase); for(int i=1;i<=m;i++){ ll cur;scanf("%lld",&cur); printf("%lld\n",query(cur)); } } }
2019-03-02
HDU 4825 Xor Sum (模板題)【01字典樹】