莫队算法 CodeForces - 617E

CodeForces - 617E 

求给定范围内异或值等于k的对数

Solution:莫队算法(听说是清华的莫涛发明的算法,所以叫莫队算法)。莫队算法可以通过改变询问的次序、分块来解决一类不修改、离线查询问题。时间复杂度O(n*sqrt(n))

听大佬的讲解,莫队算法一般其他地方都是不变的,只有add和del这两个函数会改变,这两个函数具体怎么写我也不知道,flag数组表示的含义到现在还没弄清楚,大佬说很显然......莫队为什么能通过分块将复杂度降为O(n*sqrt(n))我也不知道......

以后再慢慢学吧。

AC_code:

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define ll long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 1000010
#define maxn 1<<20
const double pi=acos(-1.0);
using namespace std;
struct node{
    int l,r,id;
}Q[maxn];

int pos[maxn];
ll ans[maxn];
ll flag[maxn];  //记录每个前缀值(异或)出现的次数
int a[maxn];
bool cmp(node a,node b)
{
    if(pos[a.l]==pos[b.l])
        return a.r<b.r;
    return pos[a.l]<pos[b.l];
}
int n,m,k;
int L=1,R=0;
ll Ans=0;
void add(int x)
{
    Ans+=flag[a[x]^k];
    flag[a[x]]++;
}
void del(int x)
{
    flag[a[x]]--;
    Ans-=flag[a[x]^k];
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    int sz=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        a[i]=a[i]^a[i-1];
        pos[i]=i/sz;
    }
    for(int i=1;i<=m;i++)

    {
        scanf("%d%d",&Q[i].l,&Q[i].r);
        Q[i].id=i;
    }
    sort(Q+1,Q+1+m,cmp);
    flag[0]=1;
    for(int i=1;i<=m;i++)
    {
        while(L<Q[i].l)
        {
            del(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)
        {
            del(R);
            R--;
        }
        ans[Q[i].id]=Ans;
    }
    for(int i=1;i<=m;i++)
        cout<<ans[i]<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/flyzer/article/details/83515290