题目传送门

https://lydsy.com/JudgeOnline/problem.php?id=2906

题解

如果可以离线的话,那么这个题目就是一个莫队的裸题。

看上去这个数据范围也还会一个根号算法,所以考虑分块。

每一次询问,我们需要知道整块的答案。如果单独知道整块看上去不太好搞,所以可以预处理整块到整块的答案。令 \(c[i][j][k]\) 表示从 \(i\) 块到 \(j\) 块 \(\leq k\) 的答案,询问的时候 \(ans\) 先加上中间整块的 \(c\) 值,然后枚举小块中的点,每个点都可以统计一次这个颜色在整块和之前统计过的部分的出现次数,然后减掉之前的,加上现在新的,就可以更新答案了。

考虑 \(c[i][j][k]\) 应该怎么求。令 \(b[i][k]\) 表示前 \(i\) 个块中出现的颜色 \(k\) 的方案数。前缀和减一下就好了。

但是如果直接按照 \(\sqrt n\) 分块的话,时空复杂度显然要炸。所以我们需要调整块大小。预处理的时空复杂度显然都是 \(O((\frac nb) ^ 2 m)\),后面的询问的复杂度是 \(O(qb)\)。当 \(b = n^{\frac 23}\) 时最优。


因此总的时间复杂度为 \(O(n^{\frac23} m + n^{\frac 23} q)\)。

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
} const int N = 50000 + 7;
const int M = 20000 + 7;
const int B = 40 + 3; #define bl(x) (((x) - 1) / blo + 1)
#define st(x) (((x) - 1) * blo + 1)
#define ed(x) std::min((x) * blo, n) int n, m, Q, blo;
int a[N];
ll sqr[N], c[B][B][M];
int b[B][M], cnt[M], pp[M]; inline void ycl() {
for (int i = 1; i <= n; ++i) sqr[i] = (ll)i * i;
for (int i = 1; i <= bl(n); ++i) {
for (int j = st(i); j <= ed(i); ++j) ++b[i][a[j]];
// for (int j = 1; j <= m; ++j) b[i][j] += b[i][j - 1];
for (int j = 1; j <= m; ++j) b[i][j] += b[i - 1][j];//, dbg("b[%d][%d] = %d\n", i, j, b[i][j]);
}
// assert(b[bl(n)][m] == n);
for (int i = 1; i <= bl(n); ++i)
for (int j = i; j <= bl(n); ++j) {
for (int k = 1; k <= m; ++k) c[i][j][k] = sqr[b[j][k] - b[i - 1][k]];//, dbg("c[%d][%d][%d] = %d\n", i, j, k, c[i][j][k]);
for (int k = 1; k <= m; ++k) c[i][j][k] += c[i][j][k - 1];
}
} inline ll qry(int l, int r, int k) {
if (k <= 0) return 0;
if (bl(l) == bl(r)) {
ll ans = 0;
for (int i = l; i <= r; ++i) if (a[i] <= k) ++cnt[a[i]], pp[a[i]] = i;
for (int i = l; i <= r; ++i) if (a[i] <= k && pp[a[i]] == i) ans += sqr[cnt[a[i]]], cnt[a[i]] = 0;
return ans;
}
ll ans = c[bl(l) + 1][bl(r) - 1][k];
// dbg("ans = %lld\n", ans);
for (int i = l; i <= ed(bl(l)); ++i) if (a[i] <= k) ++cnt[a[i]], pp[a[i]] = i;
for (int i = st(bl(r)); i <= r; ++i) if (a[i] <= k) ++cnt[a[i]], pp[a[i]] = i;
for (int i = l; i <= ed(bl(l)); ++i) if (a[i] <= k && pp[a[i]] == i) {
ans += sqr[cnt[a[i]] + b[bl(r) - 1][a[i]] - b[bl(l)][a[i]]];
ans -= sqr[b[bl(r) - 1][a[i]] - b[bl(l)][a[i]]];
cnt[a[i]] = 0;
}
for (int i = st(bl(r)); i <= r; ++i) if (a[i] <= k && pp[a[i]] == i) {
ans += sqr[cnt[a[i]] + b[bl(r) - 1][a[i]] - b[bl(l)][a[i]]];
ans -= sqr[b[bl(r) - 1][a[i]] - b[bl(l)][a[i]]];
cnt[a[i]] = 0;
}
return ans;
} inline void work() {
ycl();
ll la = 0;
while (Q--) {
int l, r, a, b;
read(l), read(r), read(a), read(b);
l ^= la, r ^= la, a ^= la, b ^= la;
assert(l <= r);
assert(r <= n);
assert(l >= 1);
assert(a <= b);
assert(b <= m);
assert(a >= 1);
printf("%lld\n", la = qry(l, r, b) - qry(l, r, a - 1));
}
} inline void init() {
read(n), read(m), read(Q);
blo = pow(n, 2.0 / 3);
// blo = ;
for (int i = 1; i <= n; ++i) read(a[i]);
// dbg("******* blo = %d\n", blo);
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}

bzoj2906 颜色 分块+块大小分析的更多相关文章

  1. BZOJ 2724蒲公英 (分块) 【内有块大小证明】

    题面 luogu传送门 分析 先分块,设块大小为x(之后我们会证明块大小取何值会更优) 步骤1 把所有的数离散化,然后对每个值开一个vector pos[i],pos[i]存储数i出现的位置 我们设查 ...

  2. LibRTMP优化之调整输出块大小

    1. 为什么要调整输出块大小 首先在RTMP_Connect0函数中LibRTMP是关闭了Nagle算法这个TCP选项的,为了实时性这样做是好的,但是要注意到LibRTMP的结构体RTMP的成员是有m ...

  3. Hadoop HDFS 文件块大小

    HDFS 文件块大小 HDFS中的文件在物理上是分块存储(block),块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在hadoop2.x版本中是128M,老版本中是64M ...

  4. Luogu 1903 数颜色 | 分块

    Luogu 1903 数颜色 | 分块 莫队不会啊-- 这道题直接分块也能卡过! 这道题的做法很有趣:对于每个位置i,记录它的颜色a[i]上一次出现的位置,记为pre[i]. 这样在查询一个区间[l, ...

  5. 调整ESX的VMFS磁盘格式的块大小,让单个虚拟磁盘支持更大容量

    调整ESX的VMFS磁盘格式的块大小,让单个虚拟磁盘支持更大容量 前因:客户搭建了VMware ESX企业版的测试平台:有一天接到一个需求,是测试数据库的,需要一个300G的磁盘. 解决过程: 1.按 ...

  6. 颜色追踪块CamShift---33

    原创博客:转载请标明出处:http://www.cnblogs.com/zxouxuewei/ 颜色追踪块CamShift滤波器. 首先确保你的kinect驱动或者uvc相机驱动能正常启动:(如果你使 ...

  7. Xamarin生成的APK大小分析

    原文:Xamarin生成的APK大小分析 刚接触Xamarin都会被Xamarin的售价吓一跳,另外就是它生成的APK大小,官方也有相关的说明,这里加上自己的理解同意讲解下: 以下是针对Android ...

  8. HDFS概述(2)————Block块大小设置

    以下内容转自:http://blog.csdn.net/samhacker/article/details/23089157?utm_source=tuicool&utm_medium=ref ...

  9. 海思板卡SATA最佳读写块大小测试

    1    引言 应需求,在海思板子上测试SATA读写速度,用dd指令,每次分别读/写不同大小的块    (bs),同时检测运行dd命令CPU占比,记录读/写速度和CPU占比. 2    实验过程 2. ...

随机推荐

  1. Python深度学习读书笔记-4.神经网络入门

    神经网络剖析   训练神经网络主要围绕以下四个方面: 层,多个层组合成网络(或模型) 输入数据和相应的目标 损失函数,即用于学习的反馈信号 优化器,决定学习过程如何进行   如图 3-1 所示:多个层 ...

  2. pip安装报错:Fatal error in launcher: Unable to create process using '"'

    pip安装包报错 解决方案: pip需要升级,可使用以下脚本: python -m pip install -U pip

  3. Mac使用SSH连接远程服务器

    1. 终端通过 ssh 连接远程服务器 ssh -p 36622 root@localhost 2. 文件上传下载 上传 scp 下载 scp 3. 客户端 FinalShell(推荐) FileZi ...

  4. python学习之requests基础

    学习地址:http://docs.python-requests.org/zh_CN/latest/user/quickstart.html#id2 使用requests发送网络请求 一.导入requ ...

  5. unity shader 热扭曲 (屏幕后处理)

      效果: c# using System; using System.Collections; using System.Collections.Generic; using UnityEngine ...

  6. 【Python】利用豆瓣短评数据生成词云

    在之前的文章中,我们获得了豆瓣爬取的短评内容,汇总到了一个文件中,但是,没有被利用起来的数据是没有意义的. 前文提到,有一篇微信推文的关于词云制作的一个实践记录,准备照此试验一下. 思路分析 读文件 ...

  7. java.lang.NoSuchMethodError: org.apache.spark.internal.Logging.$init$(Lorg/apache/spark/internal/Logging;)V

    1.sparkML的版本不对应 请参考官网找到对于版本, 比如我的 spark2.3.3          spark MLlib 也是2.3.3

  8. Springboot2.x集成Redis集群模式

    Springboot2.x集成Redis集群模式 说明 Redis集群模式是Redis高可用方案的一种实现方式,通过集群模式可以实现Redis数据多处存储,以及自动的故障转移.如果想了解更多集群模式的 ...

  9. echart 柱状图 两个纵轴坐标 刻度不一样

    在使用echart的过程中, 有的时候柱状图会使用两个纵坐标, 如果两个纵坐标的最大值是一样的还好,这样刻度也会一样. 但是多数情况下最大值是不一样的, 这样就造成了,刻度线很乱,显示不均匀. 解决办 ...

  10. ThinkPHP关联模型详解

    在ThinkPHP中,关联模型更类似一种mysql中的外键约束,但是外键约束更加安全,缺点却是在写sql语句的时候不方便,ThinkPHP很好得解决了这个问题.但是很多人不动关联模型的意思.现在就写个 ...