1. 程式人生 > >Codeforces 671E 莫隊入門

Codeforces 671E 莫隊入門

看了卿學姐的演算法講堂寫的。
使用莫隊的複雜度大約n*sqrt(n)
離線,根據l和r所在的塊排序。
在知道(L,R)的情況下要在O(1)時間內得出(L±1,R±1),所以這樣就可以向左右兩邊擴充套件區間了。
具體就是add和del函式不一樣

#include <bits/stdc++.h>
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(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++){ printf("%lld ",ans[i]); } return 0; }