2016暑期集訓10 C吳傳之火燒連營

吳傳之火燒連營

時間限制: 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章