1. 程式人生 > >清北學堂模擬賽d1t6 或和異或(xor)

清北學堂模擬賽d1t6 或和異或(xor)

格式 ring 只需要 namespace clas 信心 using names update

題目描述

LYK最近在研究位運算,它研究的主要有兩個:or和xor。(C語言中對於|和^)

為了更好的了解這兩個運算符,LYK找來了一個2^n長度的數組。它第一次先對所有相鄰兩個數執行or操作,得到一個2^(n-1)長度的數組。也就是說,如果一開始時a[1],a[2],…,a[2^n],執行完第一次操作後,會得到a[1] or a[2],a[3] or a[4] ,…, a[(2^n)-1] or a[2^n]。

第二次操作,LYK會將所有相鄰兩個數執行xor操作,得到一個2^(n-2)長度的數組,假如第一次操作後的數組是b[1],b[2],…,b[2^(n-1)],那麽執行完這次操作後會變成b[1] xor b[2], b[3] xor b[4] ,…, b[(2^(n-1))-1] xor b[2^(n-1)]。

第三次操作,LYK仍然將執行or操作,第四次LYK執行xor操作。如此交替進行。

最終這2^n個數一定會變成1個數。LYK想知道最終這個數是多少。

為了讓這個遊戲更好玩,LYK還會執行Q次修改操作。每次修改原先的2^n長度的數組中的某一個數,對於每次修改操作,你需要輸出n次操作後(最後一定只剩下唯一一個數)剩下的那個數是多少。

輸入格式(xor.in)

第一行兩個數n,Q。

接下來一行2^n個數ai表示一開始的數組。

接下來Q行,每行兩個數xi,yi,表示LYK這次的修改操作是將a{xi}改成yi。

輸出格式(xor.out)

Q行,表示每次修改操作後執行n次操作後剩下的那個數的值。

輸入樣例

2 4

1 6 3 5

1 4

3 4

1 2

1 2

輸出樣例

1

3

3

3

樣例解釋

第一次修改,{4,6,3,5}->{6,7}->{1}

第二次修改,{4,6,4,5}->{6,5}->{3}

第三次修改,{2,6,4,5}->{6,5}->{3}

第四次修改,{2,6,4,5}->{6,5}->{3}

對於30%的數據n<=17,Q=1。

對於另外20%的數據n<=10,Q<=1000。

對於再另外30%的數據n<=12,Q<=100000。

對於100%的數據1<=n<=17,1<=Q<=10^5,1<=xi<=2^n,0<=yi<2^30,0<=ai<2^30。

分析:考試的時候這道題是T3,題面又很長,就沒信心做下去直接打了個暴力,竟然還有50分,現在看,竟然就是一道裸的線段樹的題......

它的每一次操作都對應線段樹的合並操作,我們只需要記錄一下深度,看看進行哪一次操作就可以了.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n, q,maxn,c[1000010];

void build(int o, int l, int r, int dep)
{
    if (l == r)
    {
        scanf("%d", &c[o]);
        return;
    }
    int mid = (l + r) >> 1;
    build(o * 2, l, mid, dep + 1);
    build(o * 2 + 1, mid + 1, r, dep + 1);
    if ((n - dep + 1) % 2 == 1)
        c[o] = c[o * 2] | c[o * 2 + 1];
    else
        c[o] = c[o * 2] ^ c[o * 2 + 1];
}

void update(int o, int l, int r, int x, int v, int dep)
{
    if (l == r)
    {
        c[o] = v;
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid)
        update(o * 2, l, mid, x, v, dep + 1);
    if (x > mid)
        update(o * 2 + 1, mid + 1, r, x, v, dep + 1);
    if ((n - dep + 1) % 2 == 1)
        c[o] = c[o * 2] | c[o * 2 + 1];
    else
        c[o] = c[o * 2] ^ c[o * 2 + 1];
}

int main()
{
    scanf("%d%d", &n, &q);
    maxn = (1 << n);
    build(1, 1, maxn,1);
    for (int i = 1; i <= q; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        update(1, 1, maxn, x, y, 1);
        printf("%d\n", c[1]);
    }
    
    return 0;
}

清北學堂模擬賽d1t6 或和異或(xor)