首页 > 其他分享 >笔记——莫队

笔记——莫队

时间:2024-08-30 17:29:13浏览次数:4  
标签:int kMaxN 算法 笔记 ans 莫队 id

蓝月の笔记——莫队篇

简介

莫队算法是由莫涛提出的算法。在莫涛提出莫队算法之前,莫队算法已经在 Codeforces 的高手圈里小范围流传,但是莫涛是第一个对莫队算法进行详细归纳总结的人。莫涛提出莫队算法时,只分析了普通莫队算法,但是经过 OIer 和 ACMer 的集体智慧改造,莫队有了多种扩展版本。

莫队算法可以解决一类离线区间询问问题,适用性极为广泛。同时将其加以扩展,便能轻松处理树上路径询问以及支持修改操作。但是我不会

这段话是抄的

摘要

暴力乱搞做法

Prob.

Luogu P1972 [SDOI2009] HH的项链

没有特别说明都是在讲这道题

Part 1 暴力搞法

很显然,可以使用 \(O(n^2)\) 来在线回复询问,开一个 vis[] 将区间扫一遍即可

代码:

// BLuemoon_
#include <bits/stdc++.h>

using namespace std;

const int kMaxN = 1e6 + 5;

int n, m, l, r, ans, a[kMaxN], vis[kMaxN];

int main() {
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  for (cin >> m; m; m--, ans = 0) {
    cin >> l >> r, fill(vis, vis + kMaxN, 0);
	for (int i = l; i <= r; i++) {
	  ans += (vis[i] == 0), vis[i]++;
	}
	cout << ans << '\n';
  }
  return 0;
}

Part 2 普通莫队

有聪明的小朋友就要问了,不是你就一个傻逼暴力为什么要把在线标粗啊

我的评价是:感觉不如莫队

用 rzx 也想的出来莫队是一个离线算法,这明显就是一个铺垫啊

我们可以先把所有询问离线下来,进行排序,然后按照一定顺序进行拓展,就可以在 \(O(n\sqrt{n})\) 的时间复杂度内算出结果了

那又有聪明的小朋友要问了,那排序的顺序是什么呢

首先我们明显可以在 \(O(1)\) 将 \([l,r]\) 的询问拓展到相邻的 \([l,r+1],[l,r-1],[l-1,r],[l+1,r]\),那么我们可以以 \(l\) 为第一关键字,\(r\) 为第二关键字惊醒排序,这样就可以做到最优 \(O(n)\) 最坏 \(O(n^2)\) 了

为什么会被卡到 \(O(n^2)\) 呢,我们可以把询问 \([l,r]\) 抽象成平面上的点 \((l,r)\),两个询问之间的拓展次数就是他们的曼哈顿距离,有因为询问保证 \(l \le r\),所以这些点都在 \(y=x\) 之上,于是我们就可以用这样的图形来卡这种做法

用 rzx 也看的出来这么算是 \(O(n^2)\) 的,那么我们怎么优化呢,当然使用卡常界最泛用的分块啦

我们可以按 \(x\) 坐标分成 \(B\) 块,按点所在块的编号最为第一关键字,\(y\) 坐标作为第二关键字进行排序

这当块长为 \(\sqrt{n}\) 时,可以将时间复杂度降到 \(O(n\sqrt{n})\) ,懒得证明了,自己看去吧

但是我们还可以进行常数优化,因为最坏情况下从前一个块跳到后一个块可能需要 \(O(n)\) 次拓展,所以我们可以对于奇数编号按 \(y\) 坐标从小到大排序,偶数编号从大到小排序,这样就可以稍微平缓的坐过山车了

代码:

// BLuemoon_
#include <bits/stdc++.h>

using namespace std;
using LL = long long;

const int kMaxN = 1e6 + 5;

int n, m, s, L = 1, R;
LL ans, a[kMaxN], c[kMaxN];

struct Q {
  int l, r, id;
  LL ans;
  const bool operator<(const Q& _) {
    int lb = (l - 1) / s + 1, rb = (_.l / s + 1);
    if (lb != rb) {
      return lb < rb;
    }
    return (lb & 1 ? r < _.r : r > _.r);
  }
  const bool operator>(const Q& _) {
    return id < _.id;
  }
};

Q q[kMaxN];

void Insert(int x) {
  c[a[x]]++, ans += (c[a[x]] == 1);
}
void Delete(int x) {
  c[a[x]]--, ans -= (c[a[x]] == 0);
}
bool CMP(Q l, Q r) {
  return l.id < r.id;
}

int main() {
  cin >> n, s = sqrt(n);
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  cin >> m;
  for (int i = 1; i <= m; i++) {
    cin >> q[i].l >> q[i].r, q[i].id = i;
  }
  sort(q + 1, q + m + 1);
  for (int i = 1; i <= m; i++) {
    for (; R < q[i].r; Insert(++R)) {
    }
    for (; L > q[i].l; Insert(--L)) {
    }
    for (; R > q[i].r; Delete(R--)) {
    }
    for (; L < q[i].l; Delete(L++)) {
    }
    q[i].ans = ans;
  }
  sort(q + 1, q + m + 1, CMP);
  for (int i = 1; i <= m; i++) {
    cout << q[i].ans << '\n';
  }
  return 0;
}

你说的对,但是这份代码只有 \(36\) 分,因为 \(O(n\sqrt{n})\) 可能达到 \(10^9\),能过才怪,但是如果你卡卡常或许可以达到 \(50\sim 70\) 分,我在最多卡到了 \(52\),加油吧

To be continue

标签:int,kMaxN,算法,笔记,ans,莫队,id
From: https://www.cnblogs.com/bluemoon-blog/p/18389075

相关文章

  • 【Qt笔记】QListView控件详解
     目录引言一、QListView基本概念1.1定义与功能1.2架构原理二、QListView基本使用2.1创建QListView和Model2.2设置QListView的属性2.3处理用户交互三、QListView高级技巧3.1自定义委托3.2使用QStandardItemModel3.3实现拖放功能四、QListView......
  • Yolov5入门介绍(官网文档学习笔记)
    一、yolov5是什么yolov5是yolo的第五次迭代,旨在提供高速、高精度的目标检测模型官方文档:ComprehensiveGuidetoUltralyticsYOLOv5-UltralyticsYOLODocs二、yolov5的优点1、高速、高精度 (例如R-CNN目标检测有两部:先生成候选框再分类)2、基于pytorch搭建,使用于各......
  • 插入类型 DP 学习笔记
    插入类型DP形式多为nnn个元素无法重复使用,需要给定一个排列,满足一定条件或是求有多少个排列满足一定条件。nnn一般在100∼5×103100\sim5\times10^3100∼5×103左右。满足一些函数图像,类似于波浪函数,且答案与每个波浪和波浪的顶点有关(函数的xxx坐标为下标,yy......
  • C#学习笔记本--第三篇(排序算法之归并排序)
    一、基本原理://归并=递归+合并//数组分左右 //左右元素相比较//满足条件放入新数组//一侧用完放对面//递归不停分分完在排序//排序结束往上走边走边合并//走到头顶出结果//归并排序分为两部分//1.基本排序规则//2.递归平分数组//递归平分数组://不停地分割......
  • CMake构建学习笔记11-minizip库的构建
    准确来说,minizip其实是zlib提供的辅助工具,位于zlib库的contrib文件夹内。minizip提供了更为高级一点的接口,能直接操作文件进行压缩。不过,有点麻烦的是这个工具并没有提供CMake构建的方式。那么可以按照构建giflib的方式,自己组织CMakeList.txt,正好这个项目的代码量并不多。另一个......
  • nginx编译参数和配置参数笔记
    编译参数: ./configure --prefix=/etc/nginx--sbin-path=/usr/sbin/nginx--modules-path=/usr/lib64/nginx/modules--conf-path=/etc/nginx/nginx.conf--error-log-path=/var/log/nginx/error.log--http-log-path=/var/log/nginx/access.log--pid-path=/var/run/nginx.pi......
  • FFmpeg开发笔记(四十八)从0开始搭建直播系统的开源软件架构
    音视频技术的一个主要用途是直播,包括电视直播、电脑直播、手机直播等等,甚至在线课堂、在线问诊、安防监控等应用都属于直播系统的范畴。由于直播系统不仅涉及到音视频数据的编解码,还涉及到音视频数据的实时传输,因此直播领域采用的网络技术标准比较高,实现起来也比一般的WEB系统复杂......
  • 结构开发笔记(六):solidworks软件(五):绘制M2x3.0mm螺丝
    若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/141499374长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…硬件相关开发......
  • 学习笔记4——二叉树(C++版)
    关于二叉树的算法题一般都是使用递归来实现,所以要想做好二叉树的算法题,要先学会递归算法的使用。一、如何创建一个二叉树1.声明一个树节点结构体structTreeNode{intval;TreeNode*left;TreeNode*right;TreeNode(intx):val(x),left(nullptr),ri......
  • Min_25 筛学习笔记
    \(\text{Min}\_25\)筛学习笔记事实上我又学习了一个有点春的筛法。\(\text{Min}\_25\)筛用于求解积性函数的前缀和,即形如\(g(n)=\sum_{i=1}^{n}f(i)\)形式的函数\(g\)。众所周知,朴素筛法之所以无法做到低于线性是因为枚举了区间内的每一个数,那么我们想要做到低于线性,就必然......