Codeforces Round #340 (Div. 2) E XOR and Favorite Number

XOR and Favorite Number

这把CF明显题风不太对,前四道一眼题,最后来个模板题。不过正好给我科普了莫队这个姿势。莫队其实更像是一种思想,而不是一个具体的算法。总结下,它能处理的问题是无修改的区间查询,方法是按总长度的平方根分块,然后将询问排序(先按左端点所属块,再按右端点),离线求解。

这道题,先预处理前缀异或结果,记为 prefix [l,r] 的答案就是 prefix[l1] 异或 prefix[r] 。用莫队的时候,就是将左端点固定在块内(当然每次块内移动还是要花 O(n0.5) 的时间去处理的),右端点不断往后推。总复杂度 O(n1.5)

#include <bits/stdc++.h>

using namespace std;

#define ll long long

int n,m,k;
int a[100010];
int prefix[100010];

int cnt[1<<20];

struct query{
    int l;
    int r;
    int block;
    int id;
    bool operator<(const query &other)const{
        if(block!=other.block){
            return block<other.block;
        }
        return r<other.r;
    }
}qs[100010];

ll ans [100010];

int main(){ 
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        prefix[i] = prefix[i-1]^a[i];
    }

    int SQRT = sqrt(n);

    for(int i=0;i<m;i++){
        scanf("%d%d",&qs[i].l,&qs[i].r);
        qs[i].block = qs[i].l/SQRT;
        qs[i].id = i;
    }

    sort(qs,qs+m);

    int preL;
    int preR;

    ll tmp = 0;
    for(int q=0;q<m;q++){
        int L = qs[q].l;
        int R = qs[q].r;

        if(q==0 || qs[q-1].block!=qs[q].block || L>preR){   //新块或者该区间和上个区间没有交集 
            memset(cnt,0,sizeof(cnt));
            preL=L;
            preR=L-1;
            tmp=0;
            cnt[prefix[qs[q].l-1]]++;
        }else{
            //块内调整左边,注意代码顺序. 
            if(L>preL){
                for(int i=preL;i<L;i++){
                    cnt[prefix[i-1]]--;
                    tmp-=cnt[ prefix[i-1]^k ];
                }
            }else if(L<preL){
                for(int i=preL-1;i>=L;i--){
                    tmp+=cnt[ prefix[i-1]^k ];
                    cnt[prefix[i-1]]++;
                }
            }
            preL=L;
        }

        //右边界往后推 
        for(int i=preR+1;i<=R;i++){
            tmp+=cnt[ prefix[i]^k ];
            cnt[prefix[i]]++;
        }

        preR=R;
        ans[qs[q].id] = tmp;
    }

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

    return 0;
}

你可能感兴趣的:(codeforces,莫队算法,Round-#340)