codeforces 617E 莫队入门

来源:互联网 发布:马伯乐了知 编辑:程序博客网 时间:2024/06/05 00:22

莫队算法就是现将上所有的点分成sqrt(n)块,然后将要查询的区间离线起来,然后进行对[L,R]变到[L - 1,R] 、或者[L + 1,R],[L,R - 1],[L,R + 1]进行O(1)的变换。

莫队算法是优雅的暴力,复杂度O(nlogn)。

题意:给出一个一个数列,然后查询在给出区间的异或值等于k的子区间的个数。

思路:先对区间进行去前缀和处理,然后区间[L,R]的异或值为sum[R] ^sum[L - 1];然后剩下来的就是进行L,R的转移了。



#include<bits/stdc++.h>using namespace std;#define clr(x,y) memset(x,y,sizeof x)typedef long long ll;const int maxn = 2e6 + 10;int a[maxn],pos[maxn],sum[maxn];ll num[maxn];struct Node{int L,R,id;}q[maxn];bool cmp(Node p1,Node p2){    return pos[p1.L] == pos[p2.L] ? p1.R < p2.R : pos[p1.L] < pos[p2.L];}ll Ans;int n,m,k;void add(int x){    Ans += num[sum[x]^k];    num[sum[x]] ++;}void del(int x){    num[sum[x]] --;    Ans -= num[sum[x]^k];}ll ans[maxn];int main(){    // freopen("in.txt","r",stdin);    while( ~ scanf("%d%d%d",&n,&m,&k))    {        clr(num,0);sum[0] = 0;num[0] = 1;        int ss = sqrt(n);        for(int i = 1;i <= n;i ++)scanf("%d",&a[i]),pos[i] = i / ss,sum[i] = sum[i - 1] ^ a[i];        for(int i = 1; i <= m;i ++)scanf("%d%d",&q[i].L,&q[i].R),q[i].id = i;        sort(q + 1,q + m + 1,cmp);        int l = 1,r = 0;        Ans = 0;        for(int i = 1;i <= m;i ++)        {            while(l > q[i].L)            {                l --;                add(l - 1);            }            while(l < q[i].L)            {                del(l - 1);                l ++;            }            while(r > q[i].R)            {                del(r --);            }            while(r < q[i].R)            {                add(++ r);            }            ans[q[i].id] = Ans;        }        for(int i = 1;i <= m;i ++)        {            printf("%lld\n",ans[i]);        }    }    return 0;}


原创粉丝点击