1. 程式人生 > >CodeForces - 617E XOR and Favorite Number (莫隊+前綴異或和)

CodeForces - 617E XOR and Favorite Number (莫隊+前綴異或和)

cti 暴力 連續 air codeforce oid 前綴 truct iostream

題意:給你一個長為n的序列,在給你一個m次詢問,每次詢問區間內能有多少個連續子序列的異或和為k

題解:還是莫隊啊,暴力搞事情啊。假設a^b=k, 那麽我們每次莫隊add的時候只要ans加一次mp[a[x]^k]的個數就好(del同理)。對了要處理出前綴異或和,mp維護的查詢區間內的異或前綴和。因為兩個前綴異或和進行異或就能得出中間這段的異或和

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include 
<queue> #include <vector> #include <cstring> #include <iomanip> #include <set> #include<ctime> //CLOCKS_PER_SEC #define se second #define fi first #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define Pii pair<int,int> #define
Pli pair<ll,int> #define ull unsigned long long #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0) const int N=1<<20; const ull base=163; const int INF=0x3f3f3f3f; using namespace std; ll a[N]; struct node { int l,r,id; }Q[N]; int pos[N]; bool cmp(node x,node y){
if(pos[x.l]==pos[y.l])return x.r<y.r; return pos[x.l]<pos[y.l]; } int L=1,R=0; ll ans=0; ll res[N]; int n,q,k; ll mp[N]; void del(int x){ mp[a[x]]--; ans-=mp[a[x]^k]; } void add(int x){ ans+=mp[a[x]^k]; mp[a[x]]++; } int main(){ scanf("%d%d%d",&n,&q,&k); int sz=sqrt(n); for(int i=1;i<=n;i++){ scanf("%I64d",&a[i]); a[i]=a[i]^a[i-1]; pos[i]=i/sz; } for(int i=1;i<=q;i++){ scanf("%d%d",&Q[i].l,&Q[i].r); Q[i].id=i; } sort(Q+1,Q+1+q,cmp); mp[0]=1; for(int i=1;i<=q;i++){ while(L<Q[i].l){ del(L-1); L++; } while(L>Q[i].l){ L--; add(L-1); } while(R>Q[i].r){ del(R); R--; } while(R<Q[i].r){ R++; add(R); } res[Q[i].id]=ans; } for(int i=1;i<=q;i++){ printf("%I64d\n",res[i]); } return 0; }

CodeForces - 617E XOR and Favorite Number (莫隊+前綴異或和)