bzoj4241 历史研究 分块
时间:2019-10-16
本文章向大家介绍bzoj4241 历史研究 分块,主要包括bzoj4241 历史研究 分块使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目传送门
https://lydsy.com/JudgeOnline/problem.php?id=4241
题解
这道题要求出来的就是一个区间带权众数。
回忆一下一般的区间众数怎么求:
分块,对于每一次询问 \(l, r\),如果 \(l, r\) 不在同一个整块中,那么答案一定是中间的整块的众数,或者两旁的剩下来的数。
这个东西可以预处理一个 \(f[i][j]\) 表示从第 \(i\) 块到 \(j\) 的众数就可以单次 \(\sqrt n\) 求出了。
对于两旁的剩数,每个数可以预处理每个值的出现位置的序列,在上面二分求出每个数的出现次数。
可以发现上面的结论依然可以用于带权众数。
不过这道题的数据范围大了一点,有 \(10^5\),所以需要 \(O(1)\) 求出一个数在某一整段中的出现次数。因为是整段,也就是开头到结尾包含的都是整块,所以可以预处理一个前缀和 \(s[i][j]\) 表示前 \(i\) 块中 \(j\) 的出现次数就可以求出来了。
伤心,\(O((n+q)\sqrt n)\) 被 \(O((n+q)\sqrt n \log n)\) 吊打。
#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 = 1e5 + 7;
const int B = 316 + 7;
#define bl(x) (((x) - 1) / blo + 1)
#define st(x) (((x) - 1) * blo + 1)
#define ed(x) std::min((x) * blo, n)
int n, dis, Q, blo;
int a[N], b[N], s[B][N], cnt[N];
ll f[B][N];
inline void ycl() {
for (int i = 1; i <= bl(n); ++i)
for (int j = st(i); j <= ed(i); ++j) ++s[i][a[j]];
for (int i = 1; i <= bl(n); ++i)
for (int j = 1; j <= dis; ++j) s[i][j] += s[i - 1][j];
for (int i = 1; i <= bl(n); ++i) {
memset(cnt, 0, sizeof(int) * (dis + 1));
int x = st(i);
ll mx = 0;
for (int j = x; j <= n; ++j) {
smax(mx, (ll)b[a[j]] * ++cnt[a[j]]);
f[i][j] = mx;
}
}
memset(cnt, 0, sizeof(int) * (dis + 1));
}
inline ll qry(int l, int r) {
ll ans = 0;
if (bl(l) == bl(r)) {
for (int i = l; i <= r; ++i) smax(ans, (ll)b[a[i]] * ++cnt[a[i]]);
for (int i = l; i <= r; ++i) cnt[a[i]] = 0;
return ans;
}
ans = f[bl(l) + 1][r];
int sl = bl(l) + 1, sr = bl(r) - 1;
for (int i = l; i <= ed(bl(l)); ++i) smax(ans, (ll)b[a[i]] * (++cnt[a[i]] + s[sr][a[i]] - s[sl - 1][a[i]]));
for (int i = st(bl(r)); i <= r; ++i) smax(ans, (ll)b[a[i]] * (++cnt[a[i]] + s[sr][a[i]] - s[sl - 1][a[i]]));
for (int i = l; i <= ed(bl(l)); ++i) cnt[a[i]] = 0;
for (int i = st(bl(r)); i <= r; ++i) cnt[a[i]] = 0;
return ans;
}
inline void lsh() {
std::sort(b + 1, b + n + 1);
dis = std::unique(b + 1, b + n + 1) - b - 1;
for (int i = 1; i <= n; ++i) a[i] = std::lower_bound(b + 1, b + dis + 1, a[i]) - b;
}
inline void work() {
lsh();
ycl();
while (Q--) {
int l, r;
read(l), read(r);
printf("%lld\n", qry(l, r));
}
}
inline void init() {
read(n), read(Q);
blo = sqrt(n);
for (int i = 1; i <= n; ++i) read(a[i]), b[i] = a[i];
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
原文地址:https://www.cnblogs.com/hankeke/p/bzoj4241.html
- Windows Phone 7 WebBrowser 中文乱码问题
- Java并发包类总览
- 作业调度框架 Quartz.NET 2.0 beta 发布
- 系统捕获异常并发送到服务器
- 当调用GetAuthorizationGroups() 的错误-“试图访问卸载的应用程序域“(Exception from HRESULT: 0x80131014)解决方案
- WCF 4.0路由服务Routing Service
- ExpandableListView简单应用及listview模拟ExpandableListView
- 文件句柄与文件描述符
- android GifView分享
- VAE、GAN、Info-GAN:全解深度学习三大生成模型
- android获取设备唯一标示
- 如果正确读取SQL Server中的扩展事件?
- android自定义xmls文件属性
- 分布式系统中的RPC请求经常出现乱序的情况 写一个算法来将一个乱序的序列保序输出
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- (数据科学学习手札92)利用query()与eval()优化pandas代码
- Spring Boot 集成 Elasticsearch 实战
- Python之错误和异常、模块(基础系列第四篇)
- Spark存储Parquet数据到Hive,对map、array、struct字段类型的处理
- 为什么这条异常没有上报? HTTP 429
- 三问Spring事务:解决什么问题?如何解决?存在什么问题?
- 从 OAuth2 服务器获取授权授权
- NHibernate 代码映射实体类
- 使用 Castle Windsor 实现 Web API 依赖注入
- SparkSQL与Hive metastore Parquet转换
- Spark中广播变量详解以及如何动态更新广播变量
- 按需加载 AngularJS 的 Controller
- Spark SQL中Not in Subquery为何低效以及如何规避
- 踩坑记 | Flutter升级影响了NestedScrollView?
- 使用 RequireJS 加载 AngularJS