【BZOJ4241】历史研究

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)

题解:第一眼看题都感觉是莫队吧?然而听说这题卡莫队。

这题的本质是一个带权的区间众数问题,如果你会做区间众数,那么这道题也不难(当然不会做也无所谓)。

先分块,假设[a,b]是[l,r]中一段连续的整块,那么[l,r]中的带权众数∈([a,b]中的众数 U [l,a)和(b,r]中的所有数)。那么我们预处理出任意两个块(a,b)之间的带权众数(方法:枚举左边的块,在暴力扫一遍右边的所有块,用桶记录一下,维护个最大值),以及[1,a]中所有数出现的次数。处理询问时,先直接拿出中间整块的众数,再枚举两边小块的所有数即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=100010;
int n,m,nm,B;
ll ans;
struct node
{
int val,org;
}num[maxn];
int v[maxn],ref[maxn],st[maxn],s[400][maxn];
ll mx[400][400];
bool cmp(node a,node b)
{
return a.val<b.val;
}
int rd()
{
int ret=0; char gc=getchar();
while(gc<'0'||gc>'9') gc=getchar();
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret;
}
int main()
{
n=rd(),m=rd();
B=int(sqrt(double(n)));
int i,j,k,a,b,c,d;
for(i=0;i<n;i++) num[i].val=rd(),num[i].org=i;
sort(num,num+n,cmp);
for(ref[0]=-1,i=0;i<n;i++)
{
if(num[i].val>ref[nm]) ref[++nm]=num[i].val;
v[num[i].org]=nm;
}
for(i=0;i<n;i++) s[i/B][v[i]]++;
for(i=1;i*B<n;i++) for(j=1;j<=nm;j++) s[i][j]+=s[i-1][j];
for(i=0;i*B<n;i++)
{
for(j=i;j*B<n;j++)
{
mx[i][j]=mx[i][j-1];
for(k=j*B;k<j*B+B&&k<n;k++) st[v[k]]++,mx[i][j]=max(mx[i][j],(ll)st[v[k]]*ref[v[k]]);
}
memset(st,0,sizeof(st));
}
for(i=1;i<=m;i++)
{
a=rd()-1,b=rd()-1,c=a/B,d=b/B,ans=0;
if(c==d)
{
for(j=a;j<=b;j++) st[v[j]]++,ans=max(ans,(ll)st[v[j]]*ref[v[j]]);
for(j=a;j<=b;j++) st[v[j]]=0;
printf("%lld\n",ans);
continue;
}
ans=mx[c+1][d-1];
for(j=a;j<c*B+B;j++) st[v[j]]=s[d-1][v[j]]-s[c][v[j]];
for(j=d*B;j<=b;j++) st[v[j]]=s[d-1][v[j]]-s[c][v[j]];
for(j=a;j<c*B+B;j++) st[v[j]]++,ans=max(ans,(ll)st[v[j]]*ref[v[j]]);
for(j=d*B;j<=b;j++) st[v[j]]++,ans=max(ans,(ll)st[v[j]]*ref[v[j]]);
for(j=a;j<c*B+B;j++) st[v[j]]=0;
for(j=d*B;j<=b;j++) st[v[j]]=0;
printf("%lld\n",ans);
}
return 0;
}

【BZOJ4241】历史研究 分块的更多相关文章

  1. [bzoj4241][历史研究] (分块)

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

  2. bzoj4241 历史研究——分块

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4241 就是分块,预处理出从第 i 块到 j 位置的答案,以及从第 i 块到最后位置间每个数出 ...

  3. [JOISC2014]歴史の研究/[BZOJ4241]历史研究

    [JOISC2014]歴史の研究/[BZOJ4241]历史研究 题目大意: 一个长度为\(n(n\le10^5)\)的数列\(A(A_i\le10^9)\),定义一个元素对一个区间\([l,r]\)的 ...

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

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

  5. BZOJ4241 历史研究

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

  6. BZOJ4241 历史研究 莫队 堆

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目 Description IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JO ...

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

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

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

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

  9. BZOJ4241 历史研究(莫队)

    如果分块的话与区间众数没有本质区别.这里考虑莫队. 显然莫队时的删除可以用堆维护,但多了一个log不太跑得过. 有一种叫回滚莫队的trick,可以将问题变为只有加入操作.按莫队时分的块依次处理,一块中 ...

随机推荐

  1. Node.js应用场景及发展趋势

    node主要应用场景是在大前端,阿里的思路是比较合适的,但是必须要注意,绝对不能让node做太多的业务逻辑,他只适合接受人家生成好的数据,然后或渲染后,或直接发送到客户端.如果让node做复杂的业务逻 ...

  2. 判断scrollView的滑动方向

    第一种方式: float lastContentOffset; - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { las ...

  3. Codeforces Round #466 (Div. 2) B. Our Tanya is Crying Out Loud[将n变为1,有两种方式,求最小花费/贪心]

    B. Our Tanya is Crying Out Loud time limit per test 1 second memory limit per test 256 megabytes inp ...

  4. Codeforces Round #455 (Div. 2) A. Generate Login【贪心】

    A. Generate Login time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  5. Codeforces 754A Lesha and array splitting (搜索)

    题目链接 Lesha and array splitting 设s[i][j]为序列i到j的和,当s[i][j]≠0时,即可从i跳到j+1.目标为从1跳到n+1,所以按照题意暴力即可. #includ ...

  6. POJ 3264 Balanced Lineup RMQ ST算法

    题意:有n头牛,编号从1到n,每头牛的身高已知.现有q次询问,每次询问给出a,b两个数.要求给出编号在a与b之间牛身高的最大值与最小值之差. 思路:标准的RMQ问题. RMQ问题是求给定区间内的最值问 ...

  7. (入门SpringBoot)SpringBoot结合定时任务task(十)

    SpringBoot整合定时任务task 使用注解EnableScheduling在启动类上. 定义@Component作为组件被容器扫描. 表达式生成地址:http://cron.qqe2.com ...

  8. Jackson是线程安全的吗

    网上说是线程安全的,内部代码用了ThreadLocal.Synchronized这些线程安全类和关键字,可以放心的用. 避免每次使用都new一个,全局配置一个ObjectManager的对象将大大减少 ...

  9. ubuntu git 下添加 ssh

    1 ssh-keygen 产生公钥和私钥  2 cat ~/.ssh/id_rsa.pub 复制出对应的公钥, 3 拷贝到git上的ssh-key里,注意拷贝时,换行处可能会引起错误,要把换行处的空格 ...

  10. MFC中 获取新输入编辑框的内容

    //得到原始内容的长度 int len = m_editPoemFileStr.GetLength(); UpdateData(true); //得到新增加的内容 CString  sNewStrin ...