Description

IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记。JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件。
日记中记录了连续N天发生的时间,大约每天发生一件。
事件有种类之分。第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大。
JOI教授决定用如下的方法分析这些日记:
1. 选择日记中连续的一些天作为分析的时间段
2. 事件种类t的重要度为t*(这段时间内重要度为t的事件数)
3. 计算出所有事件种类的重要度,输出其中的最大值
现在你被要求制作一个帮助教授分析的程序,每次给出分析的区间,你需要输出重要度的最大值。

Input

第一行两个空格分隔的整数N和Q,表示日记一共记录了N天,询问有Q次。
接下来一行N个空格分隔的整数X1...XN,Xi表示第i天发生的事件的种类
接下来Q行,第i行(1<=i<=Q)有两个空格分隔整数Ai和Bi,表示第i次询问的区间为[Ai,Bi]。

Output

输出Q行,第i行(1<=i<=Q)一个整数,表示第i次询问的最大重要度

Sample Input

5 5
9 8 7 8 9
1 2
3 4
4 4
1 4
2 4

Sample Output

9
8
8
16
16

HINT

1<=N<=10^5
1<=Q<=10^5
1<=Xi<=10^9 (1<=i<=N)
 

  这道题刚开始时没有思路......后来发现好像和区间众数的方法有点像......

  好了,我们考虑如何做这道题。首先,我们可以把区间分块。然后,我们可以用$O(n \sqrt{n})$的复杂度求出$f_{i,j}$,表示取第$i$块到第$j$块中所有元素的答案。

  然后,我们考虑如何得到区间$[l,r]$的答案。如果$l$和$r$在同一块,那么显然扫一遍这个块就可以了。否则,我们可以先把$[l,r]$覆盖的完整的块的答案统计一下,再统计一下边角余料中答案最大的数。显然答案一定在这三者中。

  但是,统计边角余料的答案并不好做。于是,我们可以再来一个数组$cnt_{i,j}$,表示前$i$个块中第$j$号元素出现了多少次(注意先要离散化),然后我们就可以$O(1)$地统计完整的块中每种元素出现的个数了。取一下$\max$就可以了。

  下面是代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 100010
#define kuai 501 using namespace std;
typedef long long llg; int n,m,N,ln,L[kuai],R[kuai],cnt[kuai][maxn];
int a[maxn],b[maxn],lb,c[maxn],ci[maxn],be[maxn];
llg f[kuai][kuai],ans; int getint(){
int w=;bool q=;
char c=getchar();
while((c>''||c<'')&&c!='-') c=getchar();
if(c=='-') q=,c=getchar();
while(c>=''&&c<='') w=w*+c-'',c=getchar();
return q?-w:w;
} int main(){
n=getint();m=getint();
for(int i=;i<=n;i++) a[i]=b[i]=getint();
sort(b+,b+n+); lb=unique(b+,b+n+)-b-;
for(int i=;i<=n;i++){
int l=,r=lb,mid;
while(l!=r){
mid=l+r>>;
if(a[i]<=b[mid]) r=mid;
else l=mid+;
}
c[i]=l;
}
N=sqrt(n); ln=n/N; if(n%N) ln++;
for(int i=;i<ln;i++) L[i]=R[i-]+,R[i]=N*i;
L[ln]=R[ln-]+; R[ln]=n;
for(int i=,r;i<=ln;i++){
ans=; r=L[i]-;
for(int j=L[i];j<=R[i];j++) cnt[i][c[j]]++,be[j]=i;
for(int j=;j<=ln;j++){
while(r<R[j]){
r++; ci[c[r]]++;
ans=max(ans,(llg)(ci[c[r]])*(llg)a[r]);
}
f[i][j]=ans;
}
for(int j=;j<=n;j++) cnt[i][j]+=cnt[i-][j];
for(int j=;j<=lb;j++) ci[j]=;
}
while(m--){
int l=getint(),r=getint(); ans=;
if(be[l]==be[r]){
for(int i=l;i<=r;i++)
ans=max(ans,(llg)(++ci[c[i]])*(llg)a[i]);
for(int i=l;i<=r;i++) ci[c[i]]--;
}
else{
ans=f[be[l]+][be[r]-];
for(int i=l;i<=R[be[l]];i++)
ans=max(ans,(llg)((++ci[c[i]])+cnt[be[r]-][c[i]]-cnt[be[l]][c[i]])*(llg)a[i]);
for(int i=L[be[r]];i<=r;i++)
ans=max(ans,(llg)((++ci[c[i]])+cnt[be[r]-][c[i]]-cnt[be[l]][c[i]])*(llg)a[i]);
for(int i=l;i<=R[be[l]];i++) ci[c[i]]--;
for(int i=L[be[r]];i<=r;i++) ci[c[i]]--;
}
printf("%lld\n",ans);
}
return ;
}

BZOJ 4241 历史研究的更多相关文章

  1. BZOJ 4241: 历史研究——莫队 二叉堆

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4241 题意:N个int范围内的数,M次询问一个区间最大的(数字*出现次数)(加权众数),可以 ...

  2. BZOJ 4241: 历史研究 ( 回 滚 )

    题目:  链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4241 题意:给你一个长度为n序列,m次查询,每次询问 一段区间 最大的  a[ i ...

  3. bzoj 4241 历史研究——分块(区间加权众数)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4241 套路:可以大力预处理,如果求区间加权众数,可以预处理i~j块(或 j 位置)的最大值, ...

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

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

  5. BZOJ 4241 历史研究(分块)

    题意 题解 #include<iostream> #include<cstring> #include<cstdio> #include<cmath> ...

  6. 【题解】BZOJ4241: 历史研究(魔改莫队)

    [题解]BZOJ4241: 历史研究(魔改莫队) 真的是好题啊 题意 给你一个序列和很多组询问(可以离线),问你这个区间中\(\max\){元素出现个数\(\times\)元素权值} IOI国历史研究 ...

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

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

  8. BZOJ4241 历史研究

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

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

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

随机推荐

  1. 【代码笔记】iOS-把<br!>换成\n

    代码: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. // ...

  2. js location对象

    location提供了与当前窗口中加载文档有关的信息.还提供了一些导航功能.它既是window对象的属性,又是document对象的属性,window.location与document.locati ...

  3. 安装SqlServer的时候性能计数器注册表配置单元一致性失败的解决办法

    http://www.2cto.com/database/201204/126772.html

  4. Hbase安装配置(靠谱亲测)

    Hbase是Hadoop生态系统中的NoSql列式数据库.通过Hbase,可以进行数据读写,比较适合Top n场景.Hbase搭建的系统,瓶颈在于硬盘的传输速度.RDBMS一般的瓶颈在于寻道速度. 实 ...

  5. Mongodb Manual阅读笔记:CH4 管理

    4 管理 Mongodb Manual阅读笔记:CH2 Mongodb CRUD 操作Mongodb Manual阅读笔记:CH3 数据模型(Data Models)Mongodb Manual阅读笔 ...

  6. main()函数的完整形式

    初学C语言都觉得main作为整个程序的入口函数是不需要传递参数的,但事实上,我们完全可以给main()传入参数进而控制整个程序的执行,就像我们使用DOS命令传入的参数一样,这里面argc表示传入的参数 ...

  7. js中json对象和字符串的转换

    JSON.parse() : 字符串-->json对象 var str = '{"name":"huangxiaojian","age" ...

  8. netbeans设置语言

    netbeans的界面语言 默认是按系统语言 设的. 想要自己指定的话,加上以下参数就可以了. 中文 --locale zh:CN 英文 --locale en:US 日文 --locale ja:J ...

  9. Qt使用自带的windeployqt 生成exe来发布软件

    集成开发环境 QtCreator 目前生成图形界面程序 exe 大致可以分为两类:Qt Widgets Application  和 Qt Quick Application.下面分别介绍这两类exe ...

  10. POJ 1228 Grandpa's Estate --深入理解凸包

    题意: 判断凸包是否稳定. 解法: 稳定凸包每条边上至少有三个点. 这题就在于求凸包的细节了,求凸包有两种算法: 1.基于水平序的Andrew算法 2.基于极角序的Graham算法 两种算法都有一个类 ...