异或序列(莫队)

6759: 异或序列

时间限制: 1 Sec  内存限制: 128 MB
提交: 191  解决: 88
[提交] [状态] [讨论版] [命题人:admin]

题目描述

已知一个长度为n的整数数列a1,a2,…,an,给定查询参数l、r,问在al,al+1,…,ar区间内,有多少子序列满足异或和等于k。也就是说,对于所有的x,y(l≤x≤y≤r),满足ax⊕ax+1⊕⋯⊕ay=k的x,y有多少组。

 

输入

输入第一行为3个整数n,m,k。第二行为空格分开的n个整数,即a1,a2,…,an。接下来m行,每行两个整数lj,rj,代表一次查询。

 

输出

输出共m行,对应每个查询的计算结果。

 

样例输入

4 5 1
1 2 3 1
1 4
1 3
2 3
2 4
4 4

 

样例输出

4
2
1
2
1

 

提示

对于30%的数据,1≤n,m≤1000。
对于100%的数据,1≤n,m≤105,0≤k,ai≤105,1≤lj≤rj≤n。

 

来源/分类

重庆OI2018 

分析:借这个题讲一下稍微说一下莫队吧,看了几篇博客略有感悟。这个题看明白了就是一道裸莫队板子。

1、首先处理异或前缀和 a。

2、假设i到j的异或和为k,那么有a[i-1]^a[j]=k。同样也有a[j]^k=a[i-1]和a[i-1]^k=a[j]。

3、利用s[i]记录前缀和为i的有几个,那么对于当前扫到的位置x明显答案就是ans+=s[a[x]^k],同时s[a[x]]++。同样如果询问范围不在x里了要减去。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define INF 100
#define FAST_IO ios::sync_with_stdio(false)
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MAX=1e5+10;
const int mod=1e9+7;
typedef long long ll;
using namespace std;
#define gcd(a,b) __gcd(a,b)
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll qpow(ll a,ll b){ll r=1,t=a; while(b){if(b&1)r=(r*t);b>>=1;t=(t*t);}return r;}
inline ll inv1(ll b){return qpow(b,mod-2);}
inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll r=exgcd(b,a%b,y,x);y-=(a/b)*x;return r;}
inline ll read(){ll x=0,f=1;char c=getchar();for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;for(;isdigit(c);c=getchar()) x=x*10+c-'0';return x*f;}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
struct node
{
    int id,l,r;
    int block;
}mo[MAX];
int sum[MAX];
int n,m,k,len,res;
int a[MAX],ans[MAX];
int s[MAX];

int cmp(node a,node b)
{
    if(a.block==b.block)
        return a.rmo[i].l) add(--left);
        while(mo[i].rleft) del(left++);
        ans[mo[i].id]=res;
    }

    for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
    return 0;
}

 

你可能感兴趣的:(简单算法)