zoukankan      html  css  js  c++  java
  • E. XOR and Favorite Number 莫队 2038: [2009国家集训队]小Z的袜子(hose)

    一直都说学莫队,直到现在才学,训练的时候就跪了   T_T,其实挺简单的感觉。其实训练的时候也看懂了,一知半解,就想着先敲。(其实这样是不好的,应该弄懂再敲,以后要养成这个习惯)

    前缀异或也很快想出来,结果没弄好边界,也是对前缀异或和莫队的不熟练。

    CF 的E题,给定区间中有多少子区间个数异或等于k

    容易想到的是预处理前缀异或值,求解区间[L, R]的贡献,相当于在前缀异或值[L - 1, R]中任取两个数,异或值等于k

    知道区间[L, R]的贡献,可以O(1)知道[L - 1, R]和[L, R + 1]的贡献,就可以用莫队了

    把询问分块,每块大小sqrtn,然后块内按右端点排序,然后two pointer维护即可。

    因为块内的大小是sqrtn,然后每次移动只会移动sqrtn的大小。复杂度是nsqrtn

    两题都是莫队的一个应用,离线查询区间

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    const int maxn = 3000000 + 20;
    struct Query {
        int L, R, id;
    }node[maxn];
    int a[maxn];
    int n, m, k, magic;
    bool cmp(struct Query a, struct Query b) {
        if (a.L/magic != b.L/magic) return a.L/magic < b.L/magic;
        else return a.R < b.R;
    }
    LL ans[maxn];
    LL num[maxn];
    void calc() {
        LL temp = 0;
        int L = 1, R = 0;
        num[0] = 1;
        for (int i = 1; i <= m; ++i) {
            while (R < node[i].R) {
                ++R;
                temp += num[a[R] ^ k];
                num[a[R]]++;
            }
            while (R > node[i].R) { // differ sqrt
                num[a[R]]--;
                temp -= num[a[R] ^ k];
                --R;
            }
            while (L < node[i].L) {
                num[a[L - 1]]--;
                temp -= num[a[L - 1] ^ k];
                ++L;
            }
            while (L > node[i].L) {
                --L;
                temp += num[a[L - 1] ^ k];
                num[a[L - 1]]++;
            }
            ans[node[i].id] = temp;
        }
    }
    void work() {
        scanf("%d%d%d", &n, &m, &k);
        for (int i = 1; i <= n; ++i) {
            scanf("%d", a + i);
            a[i] ^= a[i - 1];
    //        printf("%d  ", a[i]);
        }
        magic = (int)sqrt(n);
        for (int i = 1; i <= m; ++i) {
            scanf("%d%d", &node[i].L, &node[i].R);
            node[i].id = i;
        }
        sort(node + 1, node + 1 + m, cmp);
        calc();
        for (int i = 1; i <= m; ++i) {
            cout << ans[i] << endl;
        }
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code
    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    const int maxn = 5e5 + 20;
    struct Query {
        int L, R, id;
        LL a, b;
        void init() {
            if (a != 0) {
                LL t = __gcd(a, b);
                a /= t, b /= t;
            } else b = 1;
        }
    }node[maxn], ans[maxn];
    int n, m, magic;
    int a[maxn];
    LL num[maxn];
    bool cmp(struct Query a, struct Query b) {
        if (a.L/magic != b.L/magic) return a.L/magic < b.L/magic;
        else return a.R < b.R;
    }
    void work() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i) {
            scanf("%d", a + i);
        }
        for (int i = 1; i <= m; ++i) {
            scanf("%d%d", &node[i].L, &node[i].R);
            node[i].id = i;
        }
        magic = sqrt(n);
        sort(node + 1, node + 1 + m, cmp);
        int L = 1, R = 0;
        LL res = 0;
        for (int i = 1; i <= m; ++i) {
            while (R < node[i].R) {
                ++R;
                res -= num[a[R]] * num[a[R]] - num[a[R]];
                num[a[R]]++;
                res += num[a[R]] * num[a[R]] - num[a[R]];
            }
            while (R > node[i].R) { //不同块之间才会出现
                res -= num[a[R]] * num[a[R]] - num[a[R]];
                num[a[R]]--;
                res += num[a[R]] * num[a[R]] - num[a[R]];
                R--;
            }
            while (L < node[i].L) { //每个块之间只是按照R排序的
                res -= num[a[L]] * num[a[L]] - num[a[L]];
                num[a[L]]--;
                res += num[a[L]] * num[a[L]] - num[a[L]];
                L++;
            }
            while (L > node[i].L) {
                --L;
                res -= num[a[L]] * num[a[L]] - num[a[L]];
                num[a[L]]++;
                res += num[a[L]] * num[a[L]] - num[a[L]];
            }
            ans[node[i].id].a = res, ans[node[i].id].b = 1LL * (node[i].R - node[i].L + 1) * (node[i].R - node[i].L);
        }
        for (int i = 1; i <= m; ++i) {
            ans[i].init();
            printf("%lld/%lld
    ", ans[i].a, ans[i].b);
        }
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    logstash 1.5.3 配置使用redis做续传
    buildbot的codebaseGenerator
    java 进程启用远程查看
    ubuntu Server 14 自动更新
    【转载】Securing Kibana + Elasticsearch
    U盘安装ubuntu server 12.04的问题检测不到CDROM的解决
    elasticsearch auto delete old indices
    elastic search 配置问题
    logstash 因为jdk版本不对造成索引时间戳失败
    ELK stack elasticsearch/logstash/kibana 关系和介绍
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7192364.html
Copyright © 2011-2022 走看看