中石油 6759: 异或序列 (莫队算法 现学现用)

已知一个长度为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

样例输出

扫描二维码关注公众号,回复: 2653654 查看本文章
4
2
1
2
1

这个题是莫队算法,之前有好多题是莫队算法,然而都没看过,所以什么都不会。今天现学现用,套莫队算法模板,看着莫队算法挺简单的,后悔,没早学,不明白的看看莫队吧https://blog.csdn.net/thinfatty/article/details/72581276  

https://www.bilibili.com/video/av4291097?from=search&seid=13758732447889923495

#include<stdio.h>
#include<queue>
#include<math.h>
#include<time.h>
#include<string.h>
#include<vector>
#include<algorithm>
#include<iostream>
#include<set>
#include<map>
#include<stack>
#define LL long long
#define mem(a,b) memset(a,b,sizeof(a))
#define lowbit(a) a&(-a)
#define PI acos(-1)
#define shortime(a)  std::ios::sync_with_stdio(a);
using  namespace std;
const LL mod=998244353;
//long long cmp(node a,node b){ if(a.x==b.x) return a.r>b.r;return a.x>b.x;}
LL  quick(LL x,LL n,LL mod){ LL ans=1,temp=x%mod; while(n){if(n%2==1){ ans=(ans*temp)%mod;} n/=2;temp=temp*temp%mod;}return ans%mod;}
int maxn (int a,int b,int c){return max(max(a,b),max(b,c));}
LL min(LL a,LL b) {return a<b?a:b;}
int gcd (int a,int b){return b==0?a:gcd(b,a%b);}
struct node {
   int l,r,id;
}Q[100005];
int n,k,m,ans[100005],flag[100005],Ans=0,b[100005];
int a[100005]={0};
int cmp (node a,node c)
{
    if(b[a.l]==b[c.l]) return a.r<c.r;
    return a.l<c.l;
}
int add(int x)
{
    Ans+=flag[a[x]^k];
    flag[a[x]]++;
}
int remove(int x)
{
    Ans-=flag[a[x]^k];
    flag[a[x]]--;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    int nx=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        a[i]=a[i]^a[i-1];
        b[i]=i/nx;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&Q[i].l,&Q[i].r);
        Q[i].id=i;
    }
    flag[0]=1;
    sort(Q,Q+m,cmp);
    int L=1,R=0;
    for(int i=1;i<=m;i++)
    {
        while(L<Q[i].l){remove(L-1);L++;}
        while(L>Q[i].l) {L--;add(L-1);}
        while(R<Q[i].r) {R++;add(R);}
        while(R>Q[i].r) {remove(R);R--;}
        ans[Q[i].id]=Ans;
    }
    for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
    return 0;
}

 补充:int add(int x)
{
    Ans+=flag[a[x]^k];
    flag[a[x]]++;
}
int remove(int x)
{
    Ans-=flag[a[x]^k];
    flag[a[x]]--;
}

这个函数可能不太容易懂,其实就是三个数异或  a^k=b; b^a=a^k^a=k;

猜你喜欢

转载自blog.csdn.net/qq_41485193/article/details/81508726