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

    (Large exttt{CF617E})

    (small exttt{In my Blog})

    这道题其实和P4462几乎一样,但是我却多调了30min,细节很多。洛谷数据太水了QwQ

    (large exttt{Meaning})

    给定 (n,m,k) ,共 (m) 个询问,每次询问一个区间,问区间内有多少个子区间的异或和等于 (k)

    (large exttt{Solution})

    题目中说是区间,则可以转化为前缀和的形式。

    (S_i=a_1~ exttt{xor}~a_2~ exttt{xor}~...~ exttt{xor}~a_i)

    (a_l~ exttt{xor}~a_{l+1}~ exttt{xor}~a_{l+2}~...~ exttt{xor}~a_r=S_r~ exttt{xor}~S_{l-1})

    然后每次询问就可转化为在 ([l-1,r]) 之间有多少个 (S_i)(S_j) ((ile j)) 使得 (S_i~ exttt{xor}~S_j=k)

    发现这个可以用莫队离线下来做,因为 (S_i~ exttt{xor}~S_j=k)(S_i~ exttt{xor}~k=S_j)(S_i) 数量改变,答案也就相应改变了。

    几个要注意的地方,坑点:

    1. 题目中没保证 (k) 不为 (0) , 即统计贡献的时候要明确,先改贡献,还是先改个数

    2. 数组的上界定为 (2e6) 不是 (1e6), 我也不知道为啥。

    然后处理好细节后,就能过了。

    (large exttt{Code})

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 2e6; //细节2
    inline int read()
    {
        register int s = 0;
        register bool neg = 0;
        register char c = getchar();
        for (; c < '0' || c > '9'; c = getchar())
            neg |= (c == '-');
        for (; c >= '0' && c <= '9'; s = s * 10 + (c ^ 48), c = getchar())
            ;
        return (neg ? -s : s);
    }
    
    int a, b, c, s[N + 10], bel[N + 10], p[N + 10], ans, Ans[N + 10];
    struct node
    {
        int l, r, id;
        bool operator<(const node &t) const
        {
            return (bel[l] ^ bel[t.l]) ? bel[l] < bel[t.l] : (bel[l] & 1 ? r < t.r : r > t.r);
        }
    } ask[N + 10];
    
    inline void add(int n)
    {
        ans += p[(n ^ c)]; //细节1
        p[n]++;
    }
    
    inline void del(int n)
    {
        p[n]--; //细节1
        ans -= p[(n ^ c)];
    }
    
    signed main()
    {
        a = read();
        b = read();
        c = read();
        int k = (int)(sqrt(a));
        for (int i = 1; i <= a; i++)
            bel[i] = (i - 1) / k + 1;
        for (int i = 1; i <= a; i++)
            s[i] = (read() ^ s[i - 1]);
        for (int i = 1; i <= b; i++)
        {
            ask[i].l = read() - 1;
            ask[i].r = read();
            ask[i].id = i;
        }
        sort(ask + 1, ask + b + 1);
        // p[0]= 1;
        int l = 1, r = 0; //其实这里左端点必须设为1,如果设为0,则要先将0这个位置计数1.
        for (int i = 1; i <= b; i++)
        {
            while (l < ask[i].l)
                del(s[l++]);
            while (l > ask[i].l)
                add(s[--l]);
            while (r < ask[i].r)
                add(s[++r]);
            while (r > ask[i].r)
                del(s[r--]);
            Ans[ask[i].id] = ans;
        }
        for (int i = 1; i <= b; i++)
            printf("%lld
    ", Ans[i]);
        return 0;
    }
    
  • 相关阅读:
    vue:路由实现原理
    webpack自定义loader和自定义插件
    JS常见的算法
    浅析DES、AES、RSA、MD5加密算法及其应用场景
    关于JSON.parse(JSON.stringify(obj))实现深拷贝应该注意的坑
    Canvas和SVG区别
    解决 webpack 打包文件体积过大
    箭头函数与普通函数的区别
    2.Linux基础命令
    1.Ubuntu系统与vmware虚拟机的安装与使用
  • 原文地址:https://www.cnblogs.com/RedreamMer/p/13533755.html
Copyright © 2011-2022 走看看