E. XOR and Favorite Number(莫队算法+异或前缀和)

传送门
1.处理出异或前缀和数组a[i]^=a[i-1];
2.对于区间[L,R]的异或和,即为a[R]^a[L-1]
3.如果x ^ y=k,那么x=k ^ y
对于一个区间[L,R],我们维护[L-1,R]的异或前缀和.
当加入新元素时a[x],如果在我们维护的前缀和里存在a[x]^k,那么就会对答案产生贡献.

##注意这个题左端点是L-1,这是关键!##

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 2000020
#define fore(n) for(int i=1;i<=n;i++)
ll n,m,k;
int a[MAXN];
ll ans[MAXN];
ll Cnt[MAXN];
int sq;
struct query // 把询问以结构体方式保存
{
    
    
    int l, r, id;
    bool operator<(const query &o) const // 重载<运算符,奇偶化排序
    {
    
    
        // 这里只需要知道每个元素归属哪个块,而块的大小都是sqrt(n),所以可以直接用l/sq
        if (l / sq != o.l / sq)
            return l < o.l;
        if (l / sq & 1)
            return r < o.r;
        return r > o.r;
    }
} Q[MAXN];
ll cur=0;
int flag=0;
inline void add(int p)
{
    
    
    cur+=Cnt[k^a[p]];
    Cnt[a[p]]++;
}
inline void del(int p)
{
    
    
    Cnt[a[p]]--;
    cur-=Cnt[k^a[p]];
}
int main()
{
    
    
    //freopen("E://tt.txt","r",stdin);
    ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    fore(n){
    
    cin>>a[i];a[i]^=a[i-1];}
    fore(m)
    {
    
    
        cin>>Q[i].l>>Q[i].r;
        Q[i].l--;
        Q[i].id=i;
    }
    sq=sqrt(n);
    sort(Q+1,Q+1+m);
    int l=0;int r=0;
    Cnt[a[0]]++;
    fore(m)
    {
    
    
        while (l < Q[i].l)
            del(l++);
        while (l > Q[i].l)
            add(--l);
        while (r < Q[i].r)
            add(++r);
        while (r > Q[i].r)
            del(r--);
 
        ans[Q[i].id]=cur;
    }
    fore(m)
    cout<<ans[i]<<endl;
}

猜你喜欢

转载自blog.csdn.net/weixin_43353639/article/details/107720215