回滚莫队例题。

这题的意思大概是

设 \(cnt_i\) 为 l ~ r 这个区间 \(i\) 出现的次数

求\(m\) 次询问 求 l~r 的 max {\(a_i\) * \(cnt_i\)}

\(n\) , \(m\) 同阶 \(1e5\)

没有强制在线? 我们考虑普通的莫队?如果最大值在某一段,当你把指针移到另一段,这个答案就失效了。

所以考虑回滚莫队。

回滚莫队的做法是

按左端点所在的块排序 如果相同 按右端点排序
然后对于每个块求解。弄个右指针在块的最右边。
分类讨论一下 如果左右指针共处一个块内 直接暴力 就是根号级别的
如果不在一个块内 由于右端点是递增的 考虑移动右端点
左边的贡献直接从 q[i].l ~ 块的最右边 暴力就行了

易证复杂度:

对于整块的询问 一共有 \(\sqrt n\) 个块 右端点每次都是当前块的右端点 所以最多移动\(n\)的长度

对于每个询问 考虑左边的端点 由于按左端点排序 左端点和右端点最多相差 \(\sqrt n\) 的长度

这样就可以做到 \(O(n \sqrt n)\) 了

// Isaunoya
#include<bits/stdc++.h>
using namespace std ;
using LL = long long ;
using uint = unsigned int ;
#define int long long
#define fir first
#define sec second
#define pb push_back
#define mp(x , y) make_pair(x , y)
template < typename T > inline void read(T & x) { x = 0 ; int f = 1 ; register char c = getchar() ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
x *= f ;
}
template < typename T > inline void print(T x) {
if(! x) { putchar('0') ; return ; }
static int st[105] ;
if(x < 0) putchar('-') , x = -x ;
int tp = 0 ;
while(x) st[++ tp] = x % 10 , x /= 10 ;
while(tp) putchar(st[tp --] + '0') ;
}
template < typename T > inline void print(T x , char c) { print(x) ; putchar(c) ; }
template < typename T , typename ...Args > inline void read(T & x , Args & ...args) { read(x) ; read(args...) ; }
template < typename T > inline void sort( vector < T > & v) { sort(v.begin() , v.end()) ; return ; }
template < typename T > inline void unique( vector < T > & v) { sort(v) ; v.erase(unique(v.begin() , v.end()) , v.end()) ; }
template < typename T > inline void cmax(T & x , T y) { if(x < y) x = y ; return ; }
template < typename T > inline void cmin(T & x , T y) { if(x > y) x = y ; return ; }
const int N = 1e5 + 10 ;
int n , m ;
int a[N] , b[N] ;
struct node { int l , r , id ; } q[N] ;
int bl[N] ;
inline bool cmp(node x , node y) {
if(bl[x.l] == bl[y.l]) return x.r < y.r ;
return bl[x.l] < bl[y.l] ;
}
int cnt[N] , cnt2[N] ;
inline int calc(int l , int r) { int ret = 0 ;
for(register int i = l ; i <= r ; i ++) { cnt2[a[i]] = 0 ; }
for(register int i = l ; i <= r ; i ++) { ++ cnt2[a[i]] ; cmax(ret , 1LL * (cnt2[a[i]]) * b[a[i]]) ; }
return ret ;
} int unt ;
int ans , Ans[N] ;
inline void add(int x) {
++ cnt[a[x]] ;
cmax(ans , 1LL * cnt[a[x]] * b[a[x]]) ;
} int now = 1 ;
inline void solve(int id) {
int qr = min(id * unt , n) , pr = qr ; memset(cnt , 0 , sizeof(cnt)) ;
ans = 0 ;
for( ; bl[q[now].l] == id ; now ++) {
if(bl[q[now].l] == bl[q[now].r]) { Ans[q[now].id] = calc(q[now].l , q[now].r) ; continue ; }
while(pr < q[now].r) { add(++ pr) ; } int last = ans ;
for(register int i = q[now].l ; i <= qr ; i ++) add(i) ;
Ans[q[now].id] = ans ;
for(register int i = q[now].l ; i <= qr ; i ++) -- cnt[a[i]] ;
ans = last ;
}
}
signed main() {
read(n , m) ;
for(register int i = 1 ; i <= n ; i ++) read(a[i]) , b[i] = a[i] ;
sort(b + 1 , b + n + 1) ; int len = unique(b + 1 , b + n + 1) - b - 1 ;
for(register int i = 1 ; i <= n ; i ++) a[i] = lower_bound(b + 1 , b + len + 1 , a[i]) - b ;
unt = sqrt(n) ;
for(register int i = 1 ; i <= n ; i ++) bl[i] = (i - 1) / unt + 1 ;
for(register int i = 1 ; i <= m ; i ++) read(q[i].l , q[i].r) , q[i].id = i ;
sort(q + 1 , q + m + 1 , cmp) ;
for(register int i = 1 ; i <= bl[n] ; i ++) solve(i) ;
for(register int i = 1 ; i <= m ;i ++) print(Ans[i] , '\n') ;
return 0 ;
}

AT1219 歴史の研究[回滚莫队学习笔记]的更多相关文章

  1. AT1219 歴史の研究 回滚莫队

    可在vj上提交:https://vjudge.net/problem/AtCoder-joisc2014_c 题意: IOI 国历史研究的第一人--JOI 教授,最近获得了一份被认为是古代 IOI 国 ...

  2. bzoj4241/AT1219 历史研究(回滚莫队)

    bzoj4241/AT1219 历史研究(回滚莫队) bzoj它爆炸了. luogu 题解时间 我怎么又在做水题. 就是区间带乘数权众数. 经典回滚莫队,一般对于延长区间简单而缩短区间难的莫队题可以考 ...

  3. BZOJ4241:历史研究(回滚莫队)

    Description IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. ...

  4. BZOJ.4241.历史研究(回滚莫队 分块)

    题目链接 \(Description\) 长度为n的数列,m次询问,每次询问一段区间最大的 \(A_i*tm_i\) (重要度*出现次数) \(Solution\) 好像可以用莫队做,但是取max的操 ...

  5. 「JOISC 2014 Day1」历史研究 --- 回滚莫队

    题目又臭又长,但其实题意很简单. 给出一个长度为\(N\)的序列与\(Q\)个询问,每个询问都对应原序列中的一个区间.对于每个查询的区间,设数\(X_{i}\)在此区间出现的次数为\(Sum_{X_{ ...

  6. BZOJ4241历史研究——回滚莫队

    题目描述 IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. 日记中记录了连 ...

  7. 2018.08.14 bzoj4241: 历史研究(回滚莫队)

    传送们 简单的回滚莫队,调了半天发现排序的时候把m达成了n... 代码: #include<bits/stdc++.h> #define N 100005 #define ll long ...

  8. bzoj4241: 历史研究(回滚莫队)

    传送门 这是一个叫做回滚莫队的神奇玩意儿 是询问,而且不强制在线,就决定是你了莫队 如果是每次插入一个数是不是很简单? 然而悲剧的是我们莫队的时候不仅要插入数字还要删除数字 那么把它变成只插入不就行了 ...

  9. 【BZOJ4241】历史研究(回滚莫队)

    题目: BZOJ4241 分析: 本校某些julao乱膜的时候发明了个"回滚邹队",大概意思就是某个姓邹的太菜了进不了省队回滚去文化课 回滚莫队裸题qwq(话说这个名字是不是莫队本 ...

随机推荐

  1. Spring学习的一点感想

    最近在学习Java体系的一些框架,先把SSM先学一遍吧,不得不说经典的Java体系带给我的冲击还是比较大的,这里不记录框架的一些实现细节,那些都记录在笔记里面了,这里记录学习 Spring 体系的一些 ...

  2. 🔥SpringBoot图文教程2—日志的使用「logback」「log4j」

    有天上飞的概念,就要有落地的实现 概念+代码实现是本文的特点,教程将涵盖完整的图文教程,代码案例 文章结尾配套自测面试题,学完技术自我测试更扎实 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例 ...

  3. selenium高级应用 - 结束Windows中浏览器的进程

    结束Windows中浏览器的进程 #-*- coding:utf-8 #结束Windows中浏览器的进程 from selenium import webdriver import unittest ...

  4. Luogu P1330 封锁阳光大学 (黑白染色)

    题意: 无向图,给一个顶点染色可以让他相邻的路不能通过,但是相邻顶点不能染色,求是否可以让所有的路不通,如果可以求最小染色数. 思路: 对于无向图中的每一个连通子图,都只有两种染色方法,或者染不了,直 ...

  5. 基于Go的马蜂窝旅游网分布式IM系统技术实践

    一.引言 即时通讯(IM)功能对于电商平台来说非常重要,特别是旅游电商. 从商品复杂性来看,一个旅游商品可能会包括用户在未来一段时间的衣.食.住.行等方方面面.从消费金额来看,往往单次消费额度较大.对 ...

  6. Docker可视化管理工具Portainer

    Portainer介绍 Portainer是Docker的图形化管理工具,提供状态显示面板.应用模板快速部署.容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作).事件日志显示.容器控制台 ...

  7. [redis读书笔记] 第一部分 数据结构与对象 压缩列表

    压缩列表是为了节省内存而设计的,是列表键和哈希键的底层实现之一. 压缩列表的逻辑如下,

  8. JAVA 对守护线程的理解

    1.在start之前,setDaemon. 该现场就成为守护线程了. 2.守护现线程并不是主线程结束,子线程(守护线程)也跟着结束.而是守护线程在没有用户线程运行的情况伴随着JVM退出而结束. 示例代 ...

  9. 开源堡垒机jumpserver的配置和使用

    开源跳板机jumpserver配置和使用 http://docs.jumpserver.org/zh/docs/quick_start.html#id9 系统设置 基本设置 # 修改url 的&quo ...

  10. debian 安装xz 命令

    # apt install -y xz-utils # xz -d Python-3.6.8.tar.xz # xz -d Python-3.6.8.tar.xz