Codeforces 671E 莫队入门

看了卿学姐的算法讲堂写的。
使用莫队的复杂度大约n*sqrt(n)
离线,根据l和r所在的块排序。
在知道(L,R)的情况下要在O(1)时间内得出(L±1,R±1),所以这样就可以向左右两边扩展区间了。
具体就是add和del函数不一样

#include 
using namespace std;
typedef long long LL;

const int maxn=1<<20;
LL a[maxn],flag[maxn];
LL ans[maxn];
int pos[maxn];

struct node{
    int l,r,id;
}Q[maxn];
int n,m,k;
LL Ans=0;
int L=1,R=0;

bool cmp(node a,node b){
    if(pos[a.l]==pos[b.l])
        return pos[a.r]<pos[b.r];
    return pos[a.l]<pos[b.l];
}

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-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(L1);
            L++;
        }
        while(L>Q[i].l){
            L--;
            add(L-1);
        }
        while(Rwhile(R>Q[i].r){
            del(R);
            R--;
        }
        ans[Q[i].id]=Ans;
    }
    for(int i=1;i<=m;i++){
        printf("%lld ",ans[i]);
    }
    return 0;
}

你可能感兴趣的:(Codeforces 671E 莫队入门)