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)也在路径上但是不出现在上述区间内,也另外加进去。

  • 相关阅读:
    android 仿微信聊天界面,以及语音录制功能
    程序员的鄙视链
    Spring 4 官方文档学习(十一)Web MVC 框架之URI Builder
    Spring 4 官方文档学习(十一)Web MVC 框架之Flash Attributes
    Spring 4 官方文档学习(十一)Web MVC 框架之resolving views 解析视图
    JDK中的序列化和反序列化
    HTTP/1.1 学习
    HttpComponents 基础接口/类与HTTP message的对应关系
    Apache HttpComponents 学习
    HttpClient学习之 客户端HTTP编程入门
  • 原文地址:https://www.cnblogs.com/purinliang/p/14226185.html
Copyright © 2011-2022 走看看