zoukankan      html  css  js  c++  java
  • 【树状数组】区间出现偶数次数的异或和(区间不同数的异或和)@ codeforce 703 D

    【树状数组】区间出现偶数次数的异或和(区间不同数的异或和)@ codeforce 703 D

    PROBLEM

    题目描述

    初始给定n个卡片拍成一排,其中第i个卡片上的数为x[i]。
    有q个询问,每次询问给定L和R表示,询问的区间【L,R】内的卡片所有出现了偶数次的数的异或和是多少。

    输入

    输入一行两个整数n,q。
    第二行n个整数,第i个数为x[i]。
    接下来q行,每行两个整数L和R,表示询问的区间。

    输出

    输出q行,其中第i行表示第i次询问的区间出现偶数次的数的异或和。

    样例输入

    3 1
    3 7 8
    1 3
    

    样例输出

    0
    

    SOlUTION

    区间内出现偶数次的数异或和 = 区间内出现奇数次的数的异或和^区间内出现过的数的异或和
    区间内出现奇数次的数的异或和 = 区间所有数的异或和
    所以,区间内出现偶数次的数异或和 = 区间所有数的异或和^区间内出现过的数的异或和


    于是问题转化成求区间内出现过的数的异或和:
    可以类比求区间内不同数的个数:树状数组离线做法
    这里树状数组sum(i)的含义就是指以当前i为结尾的前缀区间的不同数的异或和
    先对询问按右端点排序
    然后遍历每个询问,对于当前位置p,如果当前位置上的数x在之前出现过,把它在之前位置上的影响删除:

    add(last[x],x);//由异或的性质可以知道,再异或一次就可以消除影响)
    

    把它在当前位置的影响插入:

    add(p,x);
    

    更新记录最后位置的数组last[]

    CODE

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int MAXN = 1000005;
    
    int n,q,x[MAXN];
    int xorsum[MAXN],ans[MAXN];
    map<int,int> last; // last position (right-most)
    
    struct Query{
        int l,r,ind;
    }qry[MAXN];
    
    bool qcmp(Query a,Query b){
        return a.r<b.r;
    }
    
    int b[MAXN];
    
    int lowbit(int x){
        return x&-x;
    }
    
    void add(int pos,int val){
        while (pos<=n) {
            b[pos] ^= val;
            pos+=lowbit(pos);
        }
    }
    
    int sum(int pos){
        int res = 0;
        while (pos>=1){
            res ^= b[pos];
            pos-=lowbit(pos);
        }
        return res;
    }
    
    int main() {
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++){
            scanf("%d",x+i);
            xorsum[i] = xorsum[i-1]^x[i];
        }
        for(int i=1;i<=q;i++){
            scanf("%d%d",&qry[i].l,&qry[i].r);
            qry[i].ind = i;
        }
        sort(qry+1,qry+q+1,qcmp); //sort query by right endpoint
        for(int i=1,j=1;i<=q;i++){
            while (j<=qry[i].r){
                if(last[x[j]]) add(last[x[j]],x[j]); //delete pos
                last[x[j]] = j;
                add(j,x[j]); //add new pos
                j++;
            }
            ans[qry[i].ind] = sum(qry[i].r)^sum(qry[i].l-1)^xorsum[qry[i].r]^xorsum[qry[i].l-1];
        }
        for(int i=1;i<=q;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    【python-opencv】opencv基础操作之一
    【胎教】做AI的基础,开始学习。
    【实习】博士生找实习的囧事之其一
    【经验】CS
    【keras】用tensorboard监视CNN每一层的输出
    【算法】背包九讲
    【计算机网络】大数据 云计算 人工智能
    【算法】shortest distance
    【git】git hello world
    【算法】深度优先 马走日 Hamilton routes
  • 原文地址:https://www.cnblogs.com/NeilThang/p/10265972.html
Copyright © 2011-2022 走看看