• P4462 [CQOI2018]异或序列


    P4462 [CQOI2018]异或序列

    Problem:

      https://www.luogu.com.cn/problem/P4462

    Solution:

      求出异或前缀和sum[],对于 a[ l ] ^ a[ l + 1] ^ .... ^ a[ r ] 就变成了sum[ r ] ^ sum[ l - 1 ],所以最终我们要求的就是在区间 [ L,R ] 中有多少子区间 [ l,r ] 是满足 sum[ r ] ^ sum[ l - 1 ] = k 的(sum[ r ] ^ sum[ l - 1 ] = k 《==》sum[ l - 1 ] = sum[ r ] ^ k 《==》sum[ r ] = k ^ sum[ l - 1 ]),变换以下就是求 [ l - 1,r ] 区间有多少个数是等于k ^ sum[ x ] (ps:x 是当前区间中新加入的数) 

      因此题目就变成了区间记数问题,而题目中可以离线处理,所以我们就可以用莫队来写。

    #include<bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define _for(i,s,t) for(int i=s;i<t;i++)
    #define _rof(i,s,t) for(int i=s;i>t;i--)
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define per(i,s,t) for(int i=s;i>=t;i--)
    #define Ri(x) scanf("%d",&x)
    #define Rii(x,y) scanf("%d%d",&x,&y)
    #define INF 0x3f3f3f3f
    using namespace std;
    template<class T>inline void read(T &res)
    {
        char c;T flag=1;
        while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
        while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    }
    typedef long long ll;
    const int maxn = 1e5 + 10;
    int a[maxn],ans[maxn],cnt[maxn],block;
    struct Node{
        int l,r,i;
        friend bool operator < (Node n1,Node n2){
            if(n1.l/block != n2.l/block) return n1.l < n2.l;
            return n1.r < n2.r;
        }
    }nd[maxn];
    int main(){
        IOS;
        int n,m,k,v;
        cin>>n>>m>>k;
        block = sqrt(n);
        rep(i,1,n){
            cin>>v;
            a[i] = a[i - 1] ^ v;
        }
        rep(i,1,m){
            cin>>nd[i].l>>nd[i].r;
            nd[i].i = i;nd[i].l --;
        }
        sort(nd + 1,nd + 1 + m);
        int l = 1,r = 0,num = 0;
        rep(i,1,m){
            while(r < nd[i].r){
                ++r;
                num += cnt[a[r] ^ k];
                ++cnt[a[r]];
            }
            while(r > nd[i].r){
                --cnt[a[r]];
                num -= cnt[a[r] ^ k];
                --r;
            }
            while(l < nd[i].l){
                --cnt[a[l]];
                num -= cnt[a[l] ^ k];
                ++l;
            }
            while(l > nd[i].l){
                --l;
                num += cnt[a[l] ^ k];
                ++cnt[a[l]];
            }
            ans[nd[i].i] = num;
        }
        rep(i,1,n){
            cout<<ans[i]<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    对结构化学习(structured learning)的理解
    【语义分割】large kernel matters中GCN模块的pytorch实现
    【C++】使用find函数快速定位元素
    Python通过Openpyxl包汇总表格,效率提升100倍
    conda环境管理
    C++解决大数组问题
    C++ 赋值运算符重载
    [Android] java代码无错误,但跳转失败
    android 如何从activity跳转到另一个activity下指定的fragment
    绝命毒师口语精析(6)
  • 原文地址:https://www.cnblogs.com/liuzuolin/p/14339083.html
Copyright © 2020-2023  润新知