CF339D 【Xenia and Bit Operations】


AC传送门!

题目大意:

给定一个序列,每次选择一个点修改权值,然后求出全序列的值。

不难想到,直接用线段树维护就好了:

就一个单点修改

同时,在建树的时候,我们求出每一段的深度。pushup时,根据单双数来判断是按位或还是亦或运算。

code:

#include<bits/stdc++.h>
using namespace std;
#define N 1000010
#define QAQ 0

inline int read(){
    int x = 0, s = 1;
    char c = getchar();
    while(!isdigit(c)){
        if(c == '-')s = -1;
        c = getchar();
    }
    while(isdigit(c)){
        x = x * 10 + (c ^ '0');
        c = getchar();
    }
    return x * s;
}

int a[N];
struct tree{
    int w, deth;
} t[N];

inline void pushup(int o){   /*更新*/
    if(t[o].deth % 2) t[o].w = t[o << 1].w | t[o << 1 | 1].w;
    else t[o].w = t[o << 1].w ^ t[o << 1 | 1].w;
    return ;
}

void build(int o, int l, int r){
    if(l == r){
        t[o].w = a[r];
        return ;
    }
    int mid = l + r >> 1;
    build(o << 1, l, mid);
    build(o << 1 | 1, mid + 1, r);
    t[o].deth = t[o << 1].deth + 1;  /*记录深度*/
    pushup(o);
    return ;
}

void update(int o, int l, int r, int x, int k){ /*经典操作: 单点修改*/
    if(l > x || r < x) return ;
    if(l == x && r == x){
        t[o].w = k;  
        return ;
    }
    int mid = l + r >> 1;
    update(o << 1, l, mid, x, k);
    update(o << 1 | 1, mid + 1, r, x, k);
    pushup(o);
    return ;
}

int main(){
    int n = read(), m = read();
    for(int i = 1;i <= (1 << n); i++){
        a[i] = read();
    }
    build(1, 1, 1 << n);  /*千万不要忘了先建树啊!!  QAQ*/
    while(m--){
        int x = read(), y = read();
        update(1, 1, 1 << n, x, y);
        printf("%d
", t[1].w);
    }
    return QAQ;
}
原文地址:https://www.cnblogs.com/wondering-world/p/13190824.html