[CF703D]Mishka and Interesting sum/[BZOJ5476]位运算

[CF703D]Mishka and Interesting sum/[BZOJ5476]位运算

题目大意:

一个长度为(n(nle10^6))的序列(A)(m(mle10^6))次询问,每次询问区间([l,r])中,出现次数为偶数的数的异或和。

思路:

将询问离线,按照右端点排序。从左到右加入每一个数,并在该数上一次出现的位置算上贡献。显然,若一个数出现了(x)次,则只有(x-1)次对答案有贡献。这可以用树状数组维护。时间复杂度(mathcal O((n+m)log n))

源代码:

#include<map>
#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
const int N=1e6+1,M=1e6;
int n,a[N];
struct Query {
    int l,r,id;
    bool operator < (const Query &rhs) const {
        return r<rhs.r;
    }
};
Query q[M];
class FenwickTree {
    private:
        int val[N];
        int lowbit(const int &x) const {
            return x&-x;
        }
    public:
        void modify(int p,const int &x) {
            for(;p<=n;p+=lowbit(p)) {
                val[p]^=x;
            }
        }
        int query(int p) const {
            int ret=0;
            for(;p;p-=lowbit(p)) {
                ret^=val[p];
            }
            return ret;
        }
        int query(const int &l,const int &r) const {
            return query(r)^query(l-1);
        }
};
FenwickTree t;
std::map<int,int> last_pos;
int ans[M];
int main() {
    n=getint();
    for(register int i=1;i<=n;i++) {
        a[i]=getint();
    }
    const int m=getint();
    for(register int i=0;i<m;i++) {
        q[i].l=getint();
        q[i].r=getint();
        q[i].id=i;
    }
    std::sort(&q[0],&q[m]);
    for(register int i=1,j=0;i<=n;i++) {
        if(last_pos[a[i]]) {
            t.modify(last_pos[a[i]],a[i]);
        }
        for(;j<m&&q[j].r==i;j++) {
            ans[q[j].id]=t.query(q[j].l,q[j].r);
        }
        last_pos[a[i]]=i;
    }
    for(register int i=0;i<m;i++) {
        printf("%d
",ans[i]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/skylee03/p/10366760.html