1. 程式人生 > >莫隊演算法 Codeforces617E XOR and Favorite Number

莫隊演算法 Codeforces617E XOR and Favorite Number

題意:給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;
}