• 洛谷 1972 莫队


    #洛谷 1972 莫队算法

    传送门


    其实这道题的标答应该是树状数组或者线段树吧,,,如果我没记错的话曾经是做过类似题目的,,,
    然而,,然而,,

    好吧开始正题,这道题目我选择的是莫队算法,引用一下某大犇的话

    暴力出奇迹,对拍保平安

    先来讨论一下莫队算法的适用条件:

    • 莫队算法是离线算法
    • 莫队算法解决区间不修改的查询问题
    • 当已知[l,r]的值是,能在较短的时间内求出[l+1, r]或[l,r+1]的值

    莫队算法的核心思想其实就是通过调整暴力的顺序来优雅的暴力,首先把所有询问按照左端点排序,对n进行分块,将询问块按照l放入块中,然后对于每块按照右端点进行排序,之后暴力扫描,得解


    资料
    资料2


    最后%%%%%%MT大牛

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    
    
    const int maxn = 50000 + 100;
    const int maxm = 200000 + 200;
    struct task{
        int l;
        int r;
        int num;
    };
    task p[maxm];
    int ans[maxm];
    int sum[1001000];
    int tl, tr, tres;
    int a[maxn];
    int n, m;
    int blocksize;
    int blocknum;
    bool cmp1(task aa, task bb) {
        return (aa.l < bb.l);
    }
    
    bool cmp2(task aa, task bb) {
        if (aa.r == bb.r) return (aa.l < bb.l);
        return (aa.r < bb.r);
    }
    int main () {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        scanf("%d", &m);
        for (int i = 1; i <= m; i++) {
            scanf("%d %d", &p[i].l, &p[i].r);
            p[i].num = i;
        }
        std :: sort(p + 1, p + m + 1, cmp1);
        blocksize = (int)sqrt(n) + 1;
        blocknum = n / blocksize;
        int b = 1;
        int j;
        for (int i = 1; i < blocknum; i++) {
            for (j = b; p[j].l <= i * blocksize && j <= m; j++) ;
            std :: sort(&p[b], &p[j], cmp2);
            b = j;
        }
        std :: sort(&p[b], &p[m + 1], cmp2);
        tl = 1, tr = 0, tres = 0;
        for (int i = 1; i <= m; i++) {
            if (p[i].l < tl) {
                for (int j = p[i].l ; j < tl; j++) {
                    sum[a[j]]++;
                    if (sum[a[j]] == 1) tres++;
                }
            } else if (p[i].l > tl) {
                for (int j = tl; j < p[i].l; j++) {
                    sum[a[j]]--;
                    if (sum[a[j]] == 0) tres--;
                }
            }
            tl = p[i].l;
            if (p[i].r > tr) {
                for (int j = tr + 1; j <= p[i].r; j++) {
                    sum[a[j]]++;
                    if (sum[a[j]] == 1) tres++;
                }
            } else if (p[i].r < tr) {
                for (int j = p[i].r + 1; j <= tr; j++) {
                    sum[a[j]]--;
                    if (sum[a[j]] == 0) tres--;
                }
            }
            tr = p[i].r;
            ans[p[i].num] = tres;
        }
        for (int i = 1; i <= m; i++) printf("%d
    ", ans[i]);
    
    
        return 0;
    }
    
    
  • 相关阅读:
    spring security5.0源码导入idea
    汇编学习笔记(13)
    汇编学习笔记(12)
    汇编学习笔记(11)
    汇编学习笔记(10)-IO端口与指令
    汇编学习笔记(9)-汇编程序的基本语法(NASM)
    汇编学习笔记(8)-IDA+VMware调试MBR
    汇编学习笔记(7)-NASM环境搭建(nasm with vs2017)
    汇编学习笔记(6)-从MASM至NASM
    汇编学习笔记(4)-伪指令(MASM)
  • 原文地址:https://www.cnblogs.com/CtsNevermore/p/6025209.html
Copyright © 2020-2023  润新知