• Codeforces 617E XOR and Favorite Number


    题目链接

    https://codeforces.com/contest/617/problem/E

    题目大意

    给你一个长度为 N 的序列和 M 个查询,每个查询问你区间 [L , R] 中有多少子区间异或和为 K

    解题思路

    莫队 + 前缀异或和

    设 sum[i] 为序列的前 i 个数的异或和,那么根据异或性质可知一段区间 X , Y的异或和就为 sum[y] ^ sum[x - 1]

    于是可以将询问转换为区间 [L , R] 中有多少对 X , Y 使得 sum[y]  ^ sum[x - 1] = k

    设 cnt[i] 表示异或和 i 出现的次数,那么常规的做法就是对于每次询问从 L 遍历到 R 一边更新答案一遍记录前缀异或和

    map<int , int>cnt;
    for(int i = 1 ; i <= m ; i ++)
    {
        int ans = 0 ;
        cnt.clear();
        cnt[0] = 1;
        for(int j = q[i].l; j <= q[i].r ; j ++)
        {
            int now = sum[q[i].l - 1]; //把 [1 - (L - 1)] 的异或和去掉
            ans += cnt[sum[j] ^ k ^ now];
            cnt[sum[j] ^ now] ++ ;
        }
        cout << ans << '
    ';
    }

    显然这么做复杂度是肯定不行的,而题目又不涉及修改区间等操作,所以可以套个莫队离线操作

    AC_Coder

    #include<bits/stdc++.h>
    #define ios std::ios::sync_with_stdio(false)
    #define rep(i,a,n) for (int i=a;i<=n;i++)
    #define int long long
    using namespace std;
    const int N = 2e5 + 10;
    struct Q{
        int l , r , id;
    }q[N];
    int a[N] , pos[N] , sum[N] , ans[N] ;
    unordered_map<int , int>cnt;
    int n , m , k , sz , l = 1 , r , res;
    bool cmp(Q a , Q b)
    {
        if(pos[a.l] == pos[b.l]) return a.r < b.r;
        return pos[a.l] < pos[b.l];
    }
    void Add(int x)
    { 
        res += cnt[sum[x] ^ k];
        cnt[sum[x]] ++ ;
    }
    void Sub(int x)
    {
        cnt[sum[x]] -- ;
        res -= cnt[sum[x] ^ k];
    }
    signed main()
    {
        ios;
        cin >> n >> m >> k;
        sz = sqrt(n);
        rep(i , 1 , n) cin >> a[i] , sum[i] = sum[i - 1] ^ a[i] , pos[i] = i / sz;
        rep(i , 1 , m)
        {
            cin >> q[i].l >> q[i].r;
            q[i].id = i;    
        } 
        cnt[0] = 1;
        sort(q + 1 , q + 1 + m , cmp);
        rep(i , 1 , m)
        {
            while(q[i].l < l) -- l , Add(l - 1);
            while(q[i].l > l) Sub(l - 1) , l ++;
            while(q[i].r > r) Add(++ r);
            while(q[i].r < r) Sub(r --);
            ans[q[i].id] = res;
        }
        rep(i , 1 , m) cout << ans[i] << '
    ';
        return 0;
    }
    凡所不能将我击倒的,都将使我更加强大
  • 相关阅读:
    n9多媒体不显示图片处理方法
    STM32全球唯一ID读取方法
    VS2008+QT+CYAPI开发USB程序问题
    QT对话框中show和exec的区别
    华硕T20信号差的解决办法
    使用JTAG方式配置EPCS芯片时显示容量不够的解决方法
    QT中使用中文
    MODBUS CRC16
    递归的四条基本法则
    Java代码混淆和加密Jocky
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/13026194.html
Copyright © 2020-2023  润新知