码迷,mamicode.com
首页 > 其他好文 > 详细

[CQOI2018] 异或序列 - 莫队

时间:2020-07-02 22:14:14      阅读:77      评论:0      收藏:0      [点我收藏+]

标签:pac   solution   return   前缀   cpp   amp   lang   opera   一个   

Description

已知一个长度为 \(n\) 的整数数列 \(a_1,a_2,...,a_n\),给定查询参数 \(l,r\),问在 \(a_l,a_{l+1},...,a_r\) 区间内,有多少子序列满足异或和等于 \(k\)。也就是说,对于所有的 \(x,y\space (1 ≤ x ≤ y ≤ r)\),能够满足 \(a_x \bigoplus a_{x+1} \bigoplus ... \bigoplus a_y = k\)\(x,y\) 有多少组。

Solution

做出前缀异或和序列 \(s_i\),则就是求 \([l-1,r]\) 中满足 \(s_i \oplus s_j=k\)\((i,j)\) 无序对数

考虑莫队,搞一个桶 \(c[i]\) 维护当前区间所有 \(s\) 的出现,这样每次加入或删除 \(x\) 时,只需要考虑 \(x \oplus k\) 的出现即可

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 200005;

int n,a[N],s[N],c[N],m,k,sqn,ans,out[N];

struct range
{
    int l,r,id;
    bool operator < (const range &b) const
    {
        if(l/sqn==b.l/sqn) return r<b.r;
        return l<b.l;
    }
} q[N];

int l=0,r=-1;

void add(int x)
{
    ans+=c[x^k];
    c[x]++;
}

void dec(int x)
{
    c[x]--;
    ans-=c[x^k];
}

void adjust(int ql,int qr)
{
    while(r<qr) add(s[++r]);
    while(l>ql) add(s[--l]);
    while(r>qr) dec(s[r--]);
    while(l<ql) dec(s[l++]);
}

signed main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    sqn=sqrt(n);
    for(int i=1;i<=n;i++) cin>>a[i], s[i]=s[i-1]^a[i];
    for(int i=1;i<=m;i++) cin>>q[i].l>>q[i].r, q[i].l--, q[i].id=i;
    sort(q+1,q+m+1);
    for(int i=1;i<=m;i++)
    {
        adjust(q[i].l,q[i].r);
        out[q[i].id]=ans;
    }
    for(int i=1;i<=m;i++)
    {
        cout<<out[i]<<endl;
    }
}

[CQOI2018] 异或序列 - 莫队

标签:pac   solution   return   前缀   cpp   amp   lang   opera   一个   

原文地址:https://www.cnblogs.com/mollnn/p/13227015.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!