zoukankan      html  css  js  c++  java
  • CF617E XOR and Favorite Number

    BZOJ 5301 [CQOI2018]异或序列 双倍经验。

    一个区间的异或值可以用前缀和来表示,$a_l igoplus a_{l + 1}igoplus a_{l + 2} igoplus ... igoplus a_r = xorSum_r igoplus xorSum_{l - 1}$,这样子处理一下异或前缀和用莫队移动一下左右端点就可以了。

    要注意的一点就是左端点$l$在移动的时候其实不是在移动自己,每一次加入删除都是$l - 1$,因为不能取两个一样的下标异或起来算答案,所以在加入删除的时候要注意判断一下先后顺序。

    时间复杂度$O(nsqrt{n})$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    
    const int N = 1e5 + 5;
    const int M = 20;
    
    int n, qn, K, blockSiz, a[N], sum[N];
    ll nowAns = 0, cnt[1 << M];
    
    struct Querys {
        int l, r, id;
        ll res;
        
        friend bool operator < (const Querys &x, const Querys &y) {
            if(x.l / blockSiz == y.l / blockSiz) return x.r < y.r;
            else return x.l < y.l;
        }
        
    } q[N];
    
    inline void read(int &X) {
        X = 0; char ch = 0; int op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    inline void del(int now) {
        --cnt[sum[now]];
        nowAns -= cnt[sum[now] ^ K];
    }
    
    inline void add(int now) {
        nowAns += cnt[sum[now] ^ K];
        ++cnt[sum[now]];
    }
    
    inline void solve() {
        blockSiz = sqrt(n);
        sort(q + 1, q + 1 + qn);
        
    /*    for(int i = 1; i <= qn; i++)
            printf("%d %d
    ", q[i].l, q[i].r);   */
            
        cnt[0] = 1;
        for(int ln = 1, rn = 0, i = 1; i <= qn; i++) {
            for(; ln < q[i].l; del(ln - 1), ++ln);
            for(; ln > q[i].l; --ln, add(ln - 1));
            for(; rn < q[i].r; add(++rn));
            for(; rn > q[i].r; del(rn--));
            
            q[q[i].id].res = nowAns;
        }
    }
    
    int main() {
        read(n), read(qn), read(K);
        for(int i = 1; i <= n; i++) {
            read(a[i]);
            sum[i] = sum[i - 1] ^ a[i];
        }
        
    /*    for(int i = 1; i <= n + 1; i++)
            printf("%d ", sum[i]);
        printf("
    ");    */
        
        for(int i = 1; i <= qn; i++) {
            read(q[i].l), read(q[i].r);
            q[i].id = i;
        }
        
        solve();
        
        for(int i = 1; i <= qn; i++)
            printf("%lld
    ", q[i].res);
            
        return 0;
    } 
    View Code
  • 相关阅读:
    ubuntu 1804 docker install
    windows shortcut
    gallary
    g++ play
    linux profile
    terminator
    tmux
    ubuntu18
    windows toolkit
    windows terminal CLI
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9841107.html
Copyright © 2011-2022 走看看