吳傳之火燒連營
時間限制: 1 Sec 內存限制: 128 MB
題目描述
蜀漢章武元年(221年),劉備爲報吳奪荊州、關羽被殺之仇,率大軍攻吳。吳將陸遜爲避其鋒,堅守不戰,雙方成對峙之勢。蜀軍遠征,補給困難,又不能速戰速決,加上入夏以後天氣炎熱,以致銳氣漸失,士氣低落。劉備爲舒緩軍士酷熱之苦,命蜀軍在山林中安營紮寨以避暑熱。陸遜看準時機,命士兵每人帶一把茅草,到達蜀軍營壘時邊放火邊猛攻。蜀軍營寨的木柵和周圍的林木爲易燃之物,火勢迅速在各營漫延。蜀軍大亂被吳軍連破四十餘營。陸遜火燒連營的成功,決定了夷陵之戰蜀敗吳勝的結果。
劉備帶兵深入吳境,陸遜卻避而不出,蜀軍只得在山林中安營紮寨。而劉備在紮營時卻犯了兵家大忌,將兵營排列成一條直線,遠遠看去,就像是一條串着珠子的鏈,美其名曰:鏈寨。如果吳軍將領是一般人,那麼這也許不算什麼,而陸遜何許人也,他可是江東才子,能力不低於周瑜的一代儒將。他看到劉備這樣排陣,心生一計,決定用火攻破陣。然而,火計除了要有風,選定引火點也非常重要,對於劉備的佈陣,最佳引火點一定是n個兵營中的一個。而因爲風水輪流轉,每天的最佳引火點都不一樣。我們給每個兵營定下一個固定不變的火攻值Ai,每天定下一個風水值K,對於每天的最佳引火點,顯然是所有兵營中火攻值與風水值異或的結果最大的那一個兵營。然而,陸遜是個謹慎的人,他要觀察時機,在m天中選定一個最佳的進攻的日期,爲此他演算出了這m天每天的風水值,然後他希望你能夠告訴他這m天每天最大的異或結果。
輸入
第一行n,m,代表有n個兵營,m天。
接下來一行有n個非負整數,代表這n個兵營的火攻值。
接下來一行有m個非負整數,代表這m天的風水值。
輸出
輸出共m行,每行輸出一個整數,代表每天最大的異或結果。
樣例輸入
3 2
1 2 3
4 5
樣例輸出
7
7
提示
【樣例說明】
對於第1天,由於4 xor 1=5, 4 xor 2=6, 4 xor 3=7,最大異或結果爲7
對於第2天,由於5 xor 1=4, 5 xor 2=7, 5 xor 3=6,最大異或結果爲7
【數據規模和約定】
對於30%數據,n<=1000,m<=1000
對於100%數據,n<=100000,m<=100000, 0<=k,ai<=2147483647
運用trie樹 0 1 與異或
借鑑於ACTY
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
#define oo 1000000007
using namespace std;
int n,m,tot,x;
int a[50];
struct node
{
int Next[2];
void init()
{
memset(Next,-1,sizeof(Next));
}
}p[3200005];
void work(int x)
{
int k=0;
while (x)
{
a[++k]=x%2;
x/=2;
}
for (int i=k+1;i<=31;i++)
a[i]=0;
}
void update()
{
int now=0;
for (int i=31;i>=1;i--)
{
int j=a[i];
if (p[now].Next[j]==-1)
{
p[++tot].init();
p[now].Next[j]=tot;
}
now=p[now].Next[j];
}
}
int query()
{
int now=0,ret=0;
for (int i=31;i>=1;i--)
{
int j=(a[i]^1);
if (p[now].Next[j]==-1) j^=1;
if ((a[i]^j)==1) ret+=(1<<(i-1));
now=p[now].Next[j];
}
return ret;
}
int main()
{
p[0].init();
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
work(x);
update();
}
for (int j=1;j<=m;j++)
{
scanf("%d",&x);
work(x);
printf("%d\n",query());
}
return 0;
}