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;
    }
    
  • 相关阅读:
    8.10
    今日头条笔试题 1~n的每个数,按字典序排完序后,第m个数是什么?
    Gym 100500B Conference Room(最小表示法,哈希)
    CodeForces 438D The Child and Sequence(线段树)
    UVALIVE 6905 Two Yachts(最小费用最大流)
    Gym Conference Room (最小表示法,哈希)
    hdu 2389 Rain on your Parade(二分图HK算法)
    Codeforces Fox And Dinner(最大流)
    zoj 3367 Counterfeit Money(dp)
    ZOJ3370. Radio Waves(2-sat)
  • 原文地址:https://www.cnblogs.com/NeilThang/p/10265972.html
Copyright © 2011-2022 走看看