CF 365 div2 D

http://codeforces.com/contest/703/problem/D

题目大意:给你一个长度为n数组,有q个询问,每次询问一个区间[l,r],这个区间的val就是所有数值为偶数个的数的亦或值。

思路:先求出所有区间的亦或和的val,然后利用树状数组离线维护,然后用所有区间^树状数组的亦或区间就是我们所要求的区间。

原因,因为树状数组维护的区间里面保存的是奇的,所以亦或以后就是偶的了

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
const int maxn = 1e6 + 5;
vector<pair<int, int> > v[maxn];
map<int, int> m;
int a[maxn], sum[maxn], tree[maxn], ans[maxn];
int n, q;
inline int lowbit(int i) {return i & -i;}

void add(int pos, int val){
    for (int i = pos; i <= n; i += lowbit(i)){
        tree[i] ^= val;
    }
}

inline int cal(int pos){
    int res = 0;
    for (int i = pos; i >= 1; i -= lowbit(i)) res ^= tree[i];
    return res;
}

int main(){
    scanf("%d", &n);
    for (int i = 1; i <= n; i++){
        scanf("%d", a + i); sum[i] = sum[i - 1] ^ a[i];
    }
    scanf("%d", &q);
    for (int i = 1; i <= q; i++){
        int l, r; scanf("%d%d", &l, &r);
        v[r].pb(mk(l, i));
    }
    int cnt = 0;
    for (int i = 1; i <= n; i++){
        if (m[a[i]]) add(m[a[i]], a[i]);
        add(i, a[i]);
        m[a[i]] = i;
        int len = v[i].size();
        for (int j = 0; j < len; j++){
            pair<int, int> p = v[i][j];
            int res = sum[i] ^ sum[p.first - 1];
            ///printf("i = %d
", i);
            int tmp = cal(i) ^ cal(p.first - 1);
            ans[p.second] = res ^ tmp;
            if (p.first == 0 && p.second == 0) continue;
            cnt++;
            if (cnt == q) break;
        }
    }
    for (int i = 1; i <= q; i++) printf("%d
", ans[i]);
    return 0;
}
View Code

复杂度O(n*log)

原文地址:https://www.cnblogs.com/heimao5027/p/5858092.html