zoukankan      html  css  js  c++  java
  • [CQOI2018] 异或序列

    Description

    已知一个长度为 (n) 的整数数列 (a_1,a_2,...,a_n),给定查询参数 (l,r),问在 (a_l,a_{l+1},...,a_r) 区间内,有多少子序列满足异或和等于 (k)。也就是说,对于所有的 (x,yspace (1 ≤ x ≤ y ≤ r)),能够满足 (a_x igoplus a_{x+1} igoplus ... igoplus a_y = k)(x,y) 有多少组。

    Solution

    做出前缀异或和序列 (s_i),则就是求 ([l-1,r]) 中满足 (s_i oplus s_j=k)((i,j)) 无序对数

    考虑莫队,搞一个桶 (c[i]) 维护当前区间所有 (s) 的出现,这样每次加入或删除 (x) 时,只需要考虑 (x oplus k) 的出现即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 200005;
    
    int n,a[N],s[N],c[N],m,k,sqn,ans,out[N];
    
    struct range
    {
        int l,r,id;
        bool operator < (const range &b) const
        {
            if(l/sqn==b.l/sqn) return r<b.r;
            return l<b.l;
        }
    } q[N];
    
    int l=0,r=-1;
    
    void add(int x)
    {
        ans+=c[x^k];
        c[x]++;
    }
    
    void dec(int x)
    {
        c[x]--;
        ans-=c[x^k];
    }
    
    void adjust(int ql,int qr)
    {
        while(r<qr) add(s[++r]);
        while(l>ql) add(s[--l]);
        while(r>qr) dec(s[r--]);
        while(l<ql) dec(s[l++]);
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>m>>k;
        sqn=sqrt(n);
        for(int i=1;i<=n;i++) cin>>a[i], s[i]=s[i-1]^a[i];
        for(int i=1;i<=m;i++) cin>>q[i].l>>q[i].r, q[i].l--, q[i].id=i;
        sort(q+1,q+m+1);
        for(int i=1;i<=m;i++)
        {
            adjust(q[i].l,q[i].r);
            out[q[i].id]=ans;
        }
        for(int i=1;i<=m;i++)
        {
            cout<<out[i]<<endl;
        }
    }
    
    
  • 相关阅读:
    JDK5的新特性
    反射(一)类加载器、反射、动态代理
    泛型(五)
    spring自定义注解实现登陆拦截器
    java国际化
    Codeforces 231A
    Codeforces 231A
    CCF CSP 201909-2 小明种苹果(续)
    CCF CSP 201909-2 小明种苹果(续)
    CCF CSP 201909-1 小明种苹果
  • 原文地址:https://www.cnblogs.com/mollnn/p/13227015.html
Copyright © 2011-2022 走看看