bzoj2906 颜色 分块+块大小分析
题目传送门
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 颜色 分块+块大小分析的更多相关文章
- BZOJ 2724蒲公英 (分块) 【内有块大小证明】
题面 luogu传送门 分析 先分块,设块大小为x(之后我们会证明块大小取何值会更优) 步骤1 把所有的数离散化,然后对每个值开一个vector pos[i],pos[i]存储数i出现的位置 我们设查 ...
- LibRTMP优化之调整输出块大小
1. 为什么要调整输出块大小 首先在RTMP_Connect0函数中LibRTMP是关闭了Nagle算法这个TCP选项的,为了实时性这样做是好的,但是要注意到LibRTMP的结构体RTMP的成员是有m ...
- Hadoop HDFS 文件块大小
HDFS 文件块大小 HDFS中的文件在物理上是分块存储(block),块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在hadoop2.x版本中是128M,老版本中是64M ...
- Luogu 1903 数颜色 | 分块
Luogu 1903 数颜色 | 分块 莫队不会啊-- 这道题直接分块也能卡过! 这道题的做法很有趣:对于每个位置i,记录它的颜色a[i]上一次出现的位置,记为pre[i]. 这样在查询一个区间[l, ...
- 调整ESX的VMFS磁盘格式的块大小,让单个虚拟磁盘支持更大容量
调整ESX的VMFS磁盘格式的块大小,让单个虚拟磁盘支持更大容量 前因:客户搭建了VMware ESX企业版的测试平台:有一天接到一个需求,是测试数据库的,需要一个300G的磁盘. 解决过程: 1.按 ...
- 颜色追踪块CamShift---33
原创博客:转载请标明出处:http://www.cnblogs.com/zxouxuewei/ 颜色追踪块CamShift滤波器. 首先确保你的kinect驱动或者uvc相机驱动能正常启动:(如果你使 ...
- Xamarin生成的APK大小分析
原文:Xamarin生成的APK大小分析 刚接触Xamarin都会被Xamarin的售价吓一跳,另外就是它生成的APK大小,官方也有相关的说明,这里加上自己的理解同意讲解下: 以下是针对Android ...
- HDFS概述(2)————Block块大小设置
以下内容转自:http://blog.csdn.net/samhacker/article/details/23089157?utm_source=tuicool&utm_medium=ref ...
- 海思板卡SATA最佳读写块大小测试
1 引言 应需求,在海思板子上测试SATA读写速度,用dd指令,每次分别读/写不同大小的块 (bs),同时检测运行dd命令CPU占比,记录读/写速度和CPU占比. 2 实验过程 2. ...
随机推荐
- leetcode-mid-sorting and searching-162. Find Peak Element
mycode 54.81% class Solution(object): def findPeakElement(self, nums): """ :type num ...
- EDM案例讲解:Mouth foods的EDM邮件营销
你可能没有听说过Mouth foods,它是一个美味产品的在线市场.作为一个日益增长的企业,他们知道电子邮件的重要性,因为在此之前他们通过电子邮件真正找到了企业品牌中的自我,这就是为什么他们认为电子邮 ...
- 设计模式(4): 给组件实现单独的store
概述 最近最近做项目的时候总会思考一些大的应用设计模式相关的问题,我把自己的思考记录下来,供以后开发时参考,相信对其他人也有用. 组件自身的store 我们在开发组件的时候,时常都有这种需求,就是希望 ...
- 解决hibernate 序列化死循环的问题
用ie8时,请求json,eclipse直接死机!!!! 调试时,可以用chrome,看到无限循环的报错...类似 {"empty":true,"total": ...
- 网页上预览pdf文件的几种方案
网页上查看pdf的方案: 1.使用adobe reader的插件 2.使用在线office控件 3.使用火狐开源项目pdf.js(浏览器需支持html5) 4.将pdf转换为swf文件 5.使用pdf ...
- yield(),sleep()以及wait()的区别
往往混淆了这三个函数的使用. 从操作系统的角度讲,os会维护一个ready queue(就绪的线程队列).并且在某一时刻cpu只为ready queue中位于队列头部的线程服务. 但是当前正在被服务的 ...
- 【HANA系列】SAP HANA SQL获取当前日期加若干天后的日期
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL获取当前 ...
- Scratch少儿编程系列:(三)第一个例子 潜水员
一. 选择背景 在上一节系统界面的介绍中,选择"6角色"的左边,点击"从背景库中选择背景". 选择主题水下中的"underwater3". ...
- iview报错[Vue warn]: Error in render: "TypeError: ctx.injections.tableRoot.$scopedSlots[ctx.props.column.slot] is not a function"
原因是我使用了iview的<Table>组件,我给Table组件的columns中定义了4个含有slot的列,但是实际在<Table>中只使用了其中3个,导致的报错. 也就是说 ...
- stringstream istringstream ostringstream 三者的区别
stringstream istringstream ostringstream 三者的区别 说明 ostringstream : 用于执行C风格字符串的输出操作. istringstream : 用 ...