CodeForces - 617E - XOR and Favorite Number(前缀和+莫队)

我们两清 提交于 2020-03-12 12:07:05

题目链接:https://vjudge.net/problem/CodeForces-617E

题目大意:问题就是给你一个序列,问你询问的区间之内异或和为k的连续区间的数量

        如果给的n不大的话,我们可以先考虑前缀和,设a[ ]为区间异或和,如果a[l, r]的异或和等于k,那么a[r]^a[l-1]^k = a[l-1],

如果[1, 1]的异或和为k,那么a[1]^k就等于0,如果[1, 2]的异或和为k,那么a[2]^k等于0, 如果[1, 3]的异或和为k, 那么a[3]^k等

于0, 如果[2, 3]的异或和等于0呢?那它的异或和就等于a[1], 因为a[3]是[1, 3]的异或和, 如果[2, 3]异或k等于0, 那结果就[1, 1],也就是a[1]

但是光用前缀和肯定是不够的,这样的话复杂度会打到O(nm)所以说这时候就要套一个莫队算法了,另外有一个坑点是因为题目是异或所以int可能越界,注意开long long

#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define endl '\n'
#define rtl rt<<1
#define rtr rt<<1|1
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define maxx(a, b) (a > b ? a : b)
#define minn(a, b) (a < b ? a : b)
#define zero(a) memset(a, 0, sizeof(a))
#define INF(a) memset(a, 0x3f, sizeof(a))
#define IOS ios::sync_with_stdio(false)
#define _test printf("==============================================\n")
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, ll> P2;
const double pi = acos(-1.0);
const double eps = 1e-7;
const ll MOD =  1000000007LL;
const int INF = 0x3f3f3f3f;
const int _NAN = -0x3f3f3f3f;
const double EULC = 0.5772156649015328;
const int NIL = -1;
template<typename T> void read(T &x){
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
const int maxn = 1e5+10;
ll cnt[maxn*100], ans[maxn], sz;
ll arr[maxn], res, k; 
struct Q {
    int l, r, k;
    friend bool operator < (Q x, Q y) {
        int a = x.l/sz, b = y.l/sz;
        return a == b ? x.r < y.r : a < b;
    }
} q[maxn];
inline void add(int p) {
    res += cnt[arr[p]^k];
    ++cnt[arr[p]];
}  
inline void sub(int p) {
    --cnt[arr[p]];
    res -= cnt[arr[p]^k];
}
int main(void) {
    int n, m;
    scanf("%d%d%lld", &n, &m, &k);
    for (int i = 1; i<=n; ++i) {
        scanf("%lld", &arr[i]);
        arr[i] ^= arr[i-1];
    }
    for (int i = 0; i<m; ++i) {
        scanf("%d%d", &q[i].l, &q[i].r);
        q[i].k = i;
    }
    sz = sqrt(n)+eps;
    sort(q, q+m);
    cnt[0] = 1;
    int l = 1, r = 0;
    for (int i = 0; i<m; ++i) {
        while(q[i].l < l) add(--l-1);
        while(q[i].r > r) add(++r);
        while(q[i].l > l) sub(l++-1);
        while(q[i].r < r) sub(r--);
        ans[q[i].k] = res;
    }
    for (int i = 0; i<m; ++i)
        printf("%lld\n", ans[i]);
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!