莫隊演算法 Codeforces617E XOR and Favorite Number
阿新 • • 發佈:2019-01-26
題意:給n個數和一個k,有很多次查詢,每次查詢有l,r,求[l,r]有多少個子區間的xor之和等於k
思路:很明顯是個裸莫隊演算法(原來在國外也爛大街
有幾個要注意的地方,就是對於左端點操作的時候,實際上是操作L-1,以及vis和sum的更新順序
還有就是記錄數量的時候,vis陣列至少要開109w,而不是100w,因為最後的異或可能把後面的0全部填滿
區間的個數可能會爆int,所以答案要用LL存,一不小心就錯了
#include<map> #include<set> #include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<cstring> #include<iomanip> #include<iostream> #include<algorithm> #include<functional> #define fuck(x) cout<<"["<<x<<"]" #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; typedef pair<LL, int>PII; const int MX = 1e5 + 10; const int MQ = 1e5 + 10; const int MP = 2e6 + 5; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; LL ans[MX]; int n, unit, k, Qt; int vis[MP], A[MX], B[MX]; struct Que { int L, R, id; bool operator<(const Que &b)const { if(L / unit == b.L / unit) { if(R == b.R) return L < b.L; return R < b.R; } return L / unit < b.L / unit; } } Q[MQ]; void solve() { LL sum = 0; int L = 1, R = 0, c = 1; vis[0] = 1; while(c <= Qt) { while(Q[c].L < L) { L--; sum += vis[k ^ B[L - 1]]; vis[B[L - 1]]++; } while(Q[c].R > R) { R++; sum += vis[k ^ B[R]]; vis[B[R]]++; } while(Q[c].L > L) { vis[B[L - 1]]--; sum -= vis[k ^ B[L - 1]]; L++; } while(Q[c].R < R) { vis[B[R]]--; sum -= vis[k ^ B[R]]; R--; } ans[Q[c++].id] = sum; } } int main() { //FIN; scanf("%d%d%d", &n, &Qt, &k); B[0] = 0; for(int i = 1; i <= n; i++) { scanf("%d", &A[i]); B[i] = B[i - 1] ^ A[i]; } for(int i = 1; i <= Qt; i++) { scanf("%d%d", &Q[i].L, &Q[i].R); Q[i].id = i; } unit = sqrt(n + 0.5); sort(Q + 1, Q + 1 + Qt); solve(); for(int i = 1; i <= Qt; i++) { printf("%I64d\n", ans[i]); } return 0; }