CodeForces - 617E_XOR and Favorite Number(莫队)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))
#define MAXN 100000 + 10
#define MAXK 10000000 + 10
/**
题目大意
给一个数列 和数字k 多次询问[l, r]范围内 有多少各连续子序列
异或值为k
思路
没有区间修改 用莫队需要用O(1)复杂度转移
预处理 pre[x] 表示 0 ~ x 的数的异或值
则 i ~ j 的异或值为 pre[i - 1] ^ pre[j] 
当在右边增加时询问 区间内(包括开区间下届) pre[j] ^ k 的个数
当在左边增加时询问 区间内 pre[i - 1] ^ k 的个数
简单的用两个hash维护下届开区间和闭区间内的各pre个数

*/
using namespace std;

int sqn;
struct query
{
    int l, r;
    int id;
    __int64 ans;
} q[MAXN];
__int64 a[MAXN], pre[MAXN], book[MAXK], book1[MAXK], ans, k;
bool cmp(query a, query b)
{
    if (a.l / sqn == b.l / sqn)
        return a.r < b.r;
    return a.l < b.l;
}
bool CMP(query a, query b)
{
    return a.id < b.id;
}
void add(int x, bool flag)
{
    book[pre[x]]++;
    if (x > 0)
        book1[pre[x - 1]]++;
    else
        book1[0]++;
    if (flag)
    {
        if (x > 0)
            ans += book[pre[x - 1] ^ k];
        else
            ans += book[0 ^ k];
    }
    else
    {
        ans += book1[pre[x] ^ k];
    }
}
void del(int x, bool flag)
{


    if (flag)
    {
        if (x > 0)
            ans -= book[pre[x - 1] ^ k];
        else
            ans -= book[0 ^ k];
    }
    else
        ans -= book1[pre[x] ^ k];
    book[pre[x]]--;

    if (x > 0)
        book1[pre[x - 1]]--;
    else
        book1[0]--;
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
    #endif // ONLINE_JUDGE
    int n, m;
    __int64 tmp;
    mem(book, 0);
    mem(book1, 0);
    scanf("%d %d %d", &n, &m, &k);
    //cout << n << "  " << m <<endl;
    sqn = sqrt(n);
    for (int i = 0; i < n; i++)
    {
        scanf("%I64d", a + i);
        if (i == 0)
        {
            pre[i] = a[i];
            tmp = a[i];
        }
        else
        {
            pre[i] = tmp ^ a[i];
            tmp = pre[i];
        }
    }

    int l, r;
    for (int i = 0; i < m; i++)
    {
        scanf("%d %d", &l, &r);

        q[i].l = l - 1;
        q[i].r = r;
        q[i].id = i;
    }
    sort(q, q + m, cmp);

    ans = 0;
    l = r = 0;
    for (int i = 0; i < m; i++)
    {
        while (r < q[i].r)
        {
            add(r, 0);
            r++;
        }
        while (l > q[i].l)
        {
            l--;
            add(l, 1);
        }
        while (r > q[i].r)
        {
            r--;
            del(r, 0);
        }
        while (l < q[i].l)
        {
            del(l, 1);
            l++;
        }
        q[i].ans = ans;


    }
    sort(q, q + m, CMP);
    for (int i = 0; i < m; i++)
        printf("%I64d\n", q[i].ans);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/Anna__1997/article/details/78573102
今日推荐