1. 程式人生 > >HDU 4825 Xor Sum (模板題)【01字典樹】

HDU 4825 Xor Sum (模板題)【01字典樹】

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字典樹】