• 清北学堂模拟赛d1t6 或和异或(xor)


    题目描述

    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
    ", c[1]);
        }
        
        return 0;
    }
  • 相关阅读:
    Java 动态编译
    在ubuntu 18.04下,无线网卡无驱动,连不上wifi,显示wifi没有适配器的解决方法
    由浅入深了解Thrift(1,2,3)
    Docker系列05:docker镜像制作 &Docker file
    Docker系列04:docker数据存储
    Docker系列03:docker网络
    关于在github上 下载源码 clone 非 master 分支的代码
    CentOS 6 & 7 忘记root密码的修改方法
    Windows RDP远程连接CentOS 7
    Windows 上用IntelliJ Idea调试百度大数据分析框架Apache Doris FE
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7618271.html
Copyright © 2020-2023  润新知