zoukankan      html  css  js  c++  java
  • 【数据结构】莫队算法

    int n;
    
    namespace MoAlgorithm {
    
        static const int MAXM = 3e5 + 10;
        static const int MAXN = 3e5 + 10;
    
        int n, m, BLOCK;
    
        struct Node {
            int l, r, id;
    
            bool operator<(const Node &node) const {
                if (l / BLOCK != node.l / BLOCK)
                    return l < node.l;
                if ((l / BLOCK) & 1)
                    return r < node.r;
                return r > node.r;
            }
        } node[MAXM];
    
        int ans[MAXM];
    
        int L, R;
    
        int a[MAXN];
        int cnt[MAXN];
        int cntcnt[MAXN];
        int curans;
    
        void add(int x) {
            x = a[x];
            --cntcnt[cnt[x]];
            if (cnt[x] == curans)
                ++curans;
            ++cnt[x];
            ++cntcnt[cnt[x]];
        }
    
        void sub(int x) {
            x = a[x];
            --cntcnt[cnt[x]];
            if (cnt[x] == curans && cntcnt[cnt[x]] == 0)
                --curans;
            --cnt[x];
            ++cntcnt[cnt[x]];
        }
    
        void Solve() {
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; ++i)
                cnt[i] = 0;
            cntcnt[0] = n;
            for (int i = 1; i <= n; ++i)
                scanf("%d", &a[i]);
            BLOCK = (int) ceil(pow(n, 0.5));
            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);
            L = 1, R = 0, curans = 0;
            for (int i = 1; i <= m; ++i) {
                while (L > node[i].l)
                    --L, add(L);
                while (R < node[i].r)
                    ++R, add(R);
                while (L < node[i].l)
                    sub(L), ++L;
                while (R > node[i].r)
                    sub(R), --R;
                int len = R - L + 1;
                if (curans <= (len + 1) / 2)
                    ans[node[i].id] = 1;
                else
                    ans[node[i].id] = 2;
            }
            for (int i = 1; i <= m; ++i)
                printf("%d
    ", ans[i]);
        }
    
    }
    

    CF617E - XOR and Favorite Number

    统计[L,R]内有多少对(i,j)满足ij之间的所有元素异或起来等于某个常数k。这里的区间[L,R]中夹着的异或前缀和是[p[L-1],p[R]]这么多个,所以一开始初始化的时候虽然是空集但是是有p[0]在,往左拓展区间的时候是把L-1加进来,往右的时候正常把R加进来。

    namespace MoAlgorithm {
    
        static const int MAXM = 1e5 + 10;
        static const int MAXN = 1e5 + 10;
    
        int n, m, BLOCK;
    
        struct Node {
            int l, r, id;
            bool operator<(const Node &node) const {
                if (l / BLOCK != node.l / BLOCK)
                    return l < node.l;
                if ((l / BLOCK) & 1)
                    return r < node.r;
                return r > node.r;
            }
        } node[MAXM];
        ll ans[MAXM];
    
        int L, R;
        ll curans;
    
        int a[MAXN], p[MAXN];
        int k, cnt[(1 << 20)];
    
        void add(int x) {
            curans += cnt[k ^ p[x]];
            ++cnt[p[x]];
        }
    
        void sub(int x) {
            --cnt[p[x]];
            curans -= cnt[k ^ p[x]];
        }
    
        void Solve() {
            ms(cnt);
            scanf("%d%d%d", &n, &m, &k);
            for (int i = 1; i <= n; ++i) {
                scanf("%d", &a[i]);
                p[i] = p[i - 1] ^ a[i];
            }
            BLOCK = (int)ceil(pow(n, 0.5));
            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);
            L = 1, R = 0, curans = 0, cnt[p[0]] = 1;
            for (int i = 1; i <= m; ++i) {
                while (L > node[i].l)
                    --L, add(L - 1);
                while (R < node[i].r)
                    ++R, add(R);
                while (L < node[i].l)
                    sub(L - 1), ++L;
                while (R > node[i].r)
                    sub(R), --R;
                ans[node[i].id] = curans;
            }
            for (int i = 1; i <= m; ++i)
                printf("%lld
    ", ans[i]);
        }
    
    }
    

    https://codeforces.com/contest/86/problem/D
    https://codeforces.com/contest/1288/problem/E
    https://codeforces.com/contest/877/problem/F

    带修改莫队:增加一维时间T,代表在进行了T次修改之后才进行该次询问。

    树上莫队:按树的欧拉序(进入和退出某个节点都记录)一维化成一个序列,fst[x],lst[x],查询[x,y]路径的信息(不妨设fst[x]<fst[y]),当x和y是祖先/后代关系时(fst[x]<fst[y]<lst[y]<fst[x])查询[fst[x],fst[y]]就是x和y之间的节点。否则在遍历x退出之后到进入y的过程中走过的就是[x,y]的路径[lst[x],fst[y]],当然lca(x,y)也在路径上但是不出现在上述区间内,也另外加进去。

  • 相关阅读:
    poj 2312 Battle City
    poj 2002 Squares
    poj 3641 Pseudoprime numbers
    poj 3580 SuperMemo
    poj 3281 Dining
    poj 3259 Wormholes
    poj 3080 Blue Jeans
    poj 3070 Fibonacci
    poj 2887 Big String
    poj 2631 Roads in the North
  • 原文地址:https://www.cnblogs.com/purinliang/p/14226185.html
Copyright © 2011-2022 走看看