可在vj上提交:https://vjudge.net/problem/AtCoder-joisc2014_c

题意:

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

日记中记录了连续 NN 天发生的时间,大约每天发生一件。

事件有种类之分。第 ii 天发生的事件的种类用一个整数 X_iXi​ 表示,X_iXi​ 越大,事件的规模就越大。

JOI 教授决定用如下的方法分析这些日记:

  • 选择日记中连续的几天 [L,R][L,R] 作为分析的时间段;

  • 定义事件 AA 的重要度 W_AWA​ 为 A\times T_AA×TA​,其中 T_ATA​ 为该事件在区间 [L,R][L,R] 中出现的次数。

现在,您需要帮助教授求出所有事件中重要度最大的事件是哪个,并输出其重要度。

注意:教授有多组询问。

输入格式

第一行两个空格分隔的整数 NN 和 QQ,表示日记一共记录了 NN 天,询问有 QQ 次。

接下来一行 NN 个空格分隔的整数表示每天的事件种类。

接下来 QQ 行,每行给出 L,RL,R 表示一组询问。

输出格式

输出共有 QQ 行,每行一个整数,表示对应的询问的答案。

数据范围

对于 100\%100% 的数据,1\le Q,N\le 10^51≤Q,N≤105,1\le X\le 10^91≤X≤109,1\le L\le R\le 10^51≤L≤R≤105。

输入输出样例

输入 #1复制

5 5
9 8 7 8 9
1 2
3 4
4 4
1 4
2 4
输出 #1复制

9
8
8
16
16

题解:

我们首先说一下普通莫队怎么做:
首先就是对区间排序,因为我们需要找一个区间内的最大值,这个我们可以用以变量tmp来记录。
如果要添加一个数,那么我们用cnt数组来记录某个数出现的次数,并更新tmp的值
但是如果要删除一个数,虽然我们的cnt数组还可以通过减去1来保证cnt数组正确性,但是我们没有办法去更新tmp
那么要是保证tmp正确性,我们就必须对这个区间重新遍历一次,而不能在上一个区间的前提下操作。
那么如果这样操作的话,复杂度就是n*n*sqrt(n),相信这个复杂度大多题目都会TLE了

回滚莫队解决它:
首先排序函数要改一下,如果两个查询区间的左边界不在一个块,那就按照左边界从小到大排序,否则那就按照右边界从小到大排序

ll cmp(query a, query b)
{
return (belong[a.l] ^ belong[b.l]) ? belong[a.l] < belong[b.l] : a.r < b.r;
}

对于一个查询区间[l,r],我们把l叫做左边界,把r叫做右边界。使用左标记和右标记来在n个数的位置上移动

这样,对于左边界属于一个块(我们把n个数分成sqrt(n)个块)的查询区间,因为这些查询区间的右边界是递增的,所以右标记就只会向右移动,不会向左,就意味着不会出现删除元素的情况

但是这些查询区间的左边界可不一定和右边界的位置对应,也就是说对于右边界添加元素和删除元素的情况都会出现,怎么解决呢?
我们就暴力去解决,每次把左标记移动到一个查询区间的左边界,操作完之后在移动原位置(这一点可以看代码)

for(; belong[que[i].l]==k; ++i) //在同一个块内
{
ll start=que[i].l,last=que[i].r;
ll tmp;
while(r<last) //因为我们的排序函数,所以我们只需要r<last和l>start两种情况
{
++r;
++cnt[typ[r]];
now=max(now,1ll*cnt[typ[r]]*arr[r]);
}
tmp=now;
while(l > start) //将左标记回归到原位置
{
--l;
++cnt[typ[l]];
now = max(now, 1ll * cnt[typ[l]] * arr[l]);
} ans[que[i].id] = now;
while(l < rb[k] + 1)
{
--cnt[typ[l]];
l++;
}
now = tmp;
}

这个复杂度就是n*sqrt(n)。因为每次左标记都是一个固定位置,我们移动到一个查询区间的左边界这个复杂度就是sqrt(n)
因为一共有m个查询,所以m个边界(题目上说了m<=n) 所以最大复杂度就是n*sqrt(n)

然后右边界可能不在这个块内,但是右标记不需要来回移动,它只需要一直向右移动(添加元素),所以复杂度n
因为最多也就sqrt(n)个块,所以复杂度最大就是n*sqrt(n)

所以复杂度也就是n*sqrt(n)

代码:

#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <bitset>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5+10;
const int INF = 0x3f3f3f3f;
const double PI = 3.1415926;
const long long N = 1000006;
const double eps = 1e-10;
typedef long long ll;
#define mem(A, B) memset(A, B, sizeof(A))
#define lson rt<<1 , L, mid
#define rson rt<<1|1 , mid + 1, R
#define ls rt<<1
#define rs rt<<1|1
#define SIS std::ios::sync_with_stdiget_mod_new(z-x)o(false), cin.tie(0), cout.tie(0)
#define pll pair<long long, long long>
#define lowbit(abcd) (abcd & (-abcd))
#define max(a, b) ((a > b) ? (a) : (b))
#define min(a, b) ((a < b) ? (a) : (b))
inline ll read() //读取整数
{
ll res = 0;
char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)) res = (res << 1) + (res << 3) + (c ^ 48), c = getchar();
return res;
}
ll arr[maxn],cnt[maxn],cnt2[maxn],typ[maxn],inp[maxn],belong[maxn],lb[maxn],rb[maxn];
ll n,m,sizes,new_size;
ll ans[maxn];
struct query
{
ll l,r,id;
} que[maxn];
ll cmp(query a, query b)
{
return (belong[a.l] ^ belong[b.l]) ? belong[a.l] < belong[b.l] : a.r < b.r;
}
int main()
{
n=read(),m=read();
sizes=sqrt(n);
new_size=ceil((double)n/sizes);
for(ll i = 1; i <= new_size; ++i)
{
lb[i] = sizes * (i - 1) + 1;
rb[i] = sizes * i;
for(ll j = lb[i]; j <= rb[i]; ++j)
belong[j] = i;
}
rb[new_size]=n;
for(ll i=1; i<=n; ++i)
arr[i]=inp[i]=read();
sort(inp+1,inp+1+n);
ll tot=unique(inp+1,inp+1+n)-inp-1;
for(ll i=1; i<=n; ++i)
{
typ[i]=lower_bound(inp+1,1+inp+tot,arr[i])-inp;
}
for(ll i=1; i<=m; ++i)
{
que[i].l=read();
que[i].r=read();
que[i].id=i;
}
sort(que+1,que+1+m,cmp);
ll i=1;
for(ll k=1; k<=new_size; ++k)
{
ll l=rb[k]+1,r=rb[k];
ll now=0;
mem(cnt,0);
for(; belong[que[i].l]==k; ++i) //在同一个块内
{
ll start=que[i].l,last=que[i].r;
ll tmp;
if(belong[start]==belong[last]) //特判
{
tmp=0;
for(ll j=start;j<=last;++j)
{
cnt2[typ[j]]=0;
}
for(ll j=start; j<=last; ++j)
{
cnt2[typ[j]]++;
tmp=max(tmp,1ll*cnt2[typ[j]]*arr[j]);
}
ans[que[i].id]=tmp;
continue;
}
while(r<last) //因为我们的排序函数,所以我们只需要r<last和l>start两种情况
{
++r;
++cnt[typ[r]];
now=max(now,1ll*cnt[typ[r]]*arr[r]);
}
tmp=now;
while(l > start)
{
--l;
++cnt[typ[l]];
now = max(now, 1ll * cnt[typ[l]] * arr[l]);
} ans[que[i].id] = now;
while(l < rb[k] + 1)
{
--cnt[typ[l]];
l++;
}
now = tmp;
} }
for(ll i=1; i<=m; ++i) printf("%lld\n",ans[i]);
return 0;
}

AT1219 歴史の研究 回滚莫队的更多相关文章

  1. AT1219 歴史の研究[回滚莫队学习笔记]

    回滚莫队例题. 这题的意思大概是 设 \(cnt_i\) 为 l ~ r 这个区间 \(i\) 出现的次数 求\(m\) 次询问 求 l~r 的 max {\(a_i\) * \(cnt_i\)} \ ...

  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. Oracle误删数据的恢复

    Oracle误删数据的恢复,分为两种方法:SCN和时间戳两种方法恢复. 一.通过SCN恢复删除且已提交的数据 1.获得当前数据库的SCN号 select current_scn from v$data ...

  2. 【JavaWeb】JSTL 标签库

    JSTL 标签库 简介 JSTL(JSP Standard Tag Library),即 JSP 标准标签库.标签库是为了替换代码脚本,使得整个 jsp 页面变得更加简洁. JSTL 有五个功能不同的 ...

  3. 【Spring】Spring 入门

    Spring 入门 文章源码 Spring 概述 Spring Spring 是分层的 Java SE/EE 应用全栈式轻量级开源框架,以 IOC(Inverse Of Control,反转控制)和 ...

  4. 在Windows中安装MongoDB--图文并茂

    在Windows环境下安装MongoDB的方法 (1)下载MongoDB Windows版: 进入MongoDB官网 (2)设置数据文件和日志文件的存放目录: 打开刚刚安装MongoDB的目录咋bin ...

  5. Jenkins+windows+.netcore+git+iis自动化部署入门

    什么是自动化部署,就不介绍了,喜欢直接进入主题. 一. 所需环境: 1.系统为windows10 . 2.asp.net core3.1 runtime必须安装,因为我的代码是asp.net core ...

  6. iconv函数报错 Detected an illegal character in input string

    近日使用php代码导出文件为excel,一直乱码.导出修改编码都无效,最后发现,是需要修改php导出代码本身的编码.首先用记事本打开php代码,另存为,选择ANSI格式.然后打开iconv函数这个ph ...

  7. 【Linux】如何查看命令来源于哪个包

    Debian:(Ubuntu等) 先安装apt-file sudo apt-get install -y apt-file apt-file update 查询命令:(已查询ifconfig为例) r ...

  8. 量子化学Gaussian技术实战课 2021年4月9号--12号 远程在线教学

    材料模拟分子动力学课程 3月19号--22号 远程在线课 lammps分子动力学课程 3月12号--15号 远程在线课 第一性原理VASP实战课 3月25号-28号 远程在线课 量子化学Gaussia ...

  9. Django实现文件在本地的存储和读取

    需求介绍:将图片存入本地的电脑文件夹中,将图片的路径保存到数据库,然后通过数据库的路径读取文件: 1.文件的存入: 前端文件: <form class="form-horizontal ...

  10. Spring基于注解开发的注解使用之AOP(部分源代码分析)

    AOP底层实现动态代理 1.导入spring-aop包依赖 <!--aopV1--> <dependency> <groupId>org.springframewo ...