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

题目大意:

一个长度为\(n(n\le10^5)\)的数列\(A(A_i\le10^9)\),定义一个元素对一个区间\([l,r]\)的贡献为\(A_i\times cnt(A_i)\),其中\(cnt(A_i)\)表示\(A_i\)在区间内的出现次数。\(q(q\le10^5)\)次询问,每次询问一个区间内贡献最大的元素的贡献。

思路:

分块。

\(cnt[i][j]\)表示前\(i\)块内\(j\)的出现次数,\(sum[i][j]\)表示\([begin(i),end(j)]\)的答案。

对\(A\)离散化后预处理\(cnt\)和\(sum\),询问时如果\(l,r\)在同一块直接暴力。如果不在同一块,则答案要么是\(sum[bel(l)+1,bel(r)-1]\),要么是\(l,r\)所在块中出现过的元素的贡献。

时间复杂度\(\mathcal O(n^{\frac32})\)。

源代码:

#include<cmath>
#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
typedef long long int64;
const int N=1e5,M=317;
int n,m,q,block,a[N],b[N],bel[N],begin[M],end[M],tmp[N],cnt[M][N];
int64 sum[M][M];
inline int64 query(const int &l,const int &r) {
int64 ret=0;
if(bel[l]==bel[r]) {
for(register int i=l;i<=r;i++) {
tmp[a[i]]++;
ret=std::max(ret,(int64)b[a[i]]*tmp[a[i]]);
}
for(register int i=l;i<=r;i++) tmp[a[i]]--;
return ret;
}
ret=sum[bel[l]+1][bel[r]-1];
for(register int i=l;i<=end[bel[l]];i++) {
tmp[a[i]]++;
ret=std::max(ret,(int64)b[a[i]]*(tmp[a[i]]+cnt[bel[r]-1][a[i]]-cnt[bel[l]][a[i]]));
}
for(register int i=begin[bel[r]];i<=r;i++) {
tmp[a[i]]++;
ret=std::max(ret,(int64)b[a[i]]*(tmp[a[i]]+cnt[bel[r]-1][a[i]]-cnt[bel[l]][a[i]]));
}
for(register int i=l;i<=end[bel[l]];i++) tmp[a[i]]--;
for(register int i=begin[bel[r]];i<=r;i++) tmp[a[i]]--;
return ret;
}
int main() {
n=getint(),q=getint(),block=sqrt(n);
for(register int i=0;i<n;i++) {
a[i]=b[i]=getint();
bel[i]=i/block;
end[bel[i]]=i;
}
for(register int i=n-1;i>=0;i--) {
begin[bel[i]]=i;
}
std::sort(&b[0],&b[n]);
m=std::unique(&b[0],&b[n])-b;
for(register int i=0;i<n;i++) {
a[i]=std::lower_bound(&b[0],&b[m],a[i])-b;
cnt[bel[i]][a[i]]++;
}
for(register int i=1;i<=bel[n-1];i++) {
for(register int j=0;j<m;j++) {
cnt[i][j]+=cnt[i-1][j];
}
}
for(register int i=0;i<=bel[n-1];i++) {
for(register int j=begin[i];j<=end[i];j++) {
tmp[a[j]]++;
sum[i][i]=std::max(sum[i][i],(int64)b[a[j]]*tmp[a[j]]);
}
for(register int j=begin[i];j<=end[i];j++) tmp[a[j]]--;
for(register int j=i+1;j<=bel[n-1];j++) {
sum[i][j]=sum[i][j-1];
for(register int k=begin[j];k<=end[j];k++) {
tmp[a[k]]++;
sum[i][j]=std::max(sum[i][j],(int64)b[a[k]]*(tmp[a[k]]+cnt[j-1][a[k]]-(i!=0?cnt[i-1][a[k]]:0)));
}
for(register int k=begin[j];k<=end[j];k++) tmp[a[k]]--;
}
}
for(register int i=0;i<q;i++) {
const int l=getint()-1,r=getint()-1;
printf("%lld\n",query(l,r));
}
return 0;
}

[JOISC2014]歴史の研究/[BZOJ4241]历史研究的更多相关文章

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

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

  2. BZOJ4241 历史研究

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

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

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

  4. BZOJ4241 历史研究 莫队 堆

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

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

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

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

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

  7. BZOJ4241 历史研究(莫队)

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

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

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

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

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

随机推荐

  1. 嵌入式Linux截图工具gsnap移植与分析【转】

    转自:http://blog.csdn.net/lu_embedded/article/details/53934184 版权声明:开心源自分享,快乐源于生活 —— 分享技术,传递快乐.转载文章请注明 ...

  2. Linux修改主机名【转】

    一.永久修改修改/etc/sysconfig/network,在里面指定主机名称HOSTNAME=然后执行命令hostname 主机名这个时候可以注销一下系统,再重登录之后就行了. 或者修改/etc/ ...

  3. Python和MySQL数据库交互PyMySQL

    Python数据库操作 对于关系型数据库的访问,Python社区已经指定了一个标准,称为Python Database API SepcificationV2.0.MySQL.Qracle等特定数据库 ...

  4. python-windows下将单个py文件生成exe

    突然要生成一个exe给其他人用.紧急搜索下了 命令行参数获取用如下方法 from sys import argv base64path = argv[1] argv这个元组就是你的参数列表了,同C一样 ...

  5. js中this揭秘

    前端面试题中经常会考this指向问题,初学者通常都会晕头转向,不知所以然.今天我就来讲讲js中this指向问题. this指向大概分为5种情况,记住这6个规律,基本上面试题都能解决. 通过圆括号直接调 ...

  6. ASP .Net Core系统部署到Ubuntu 16.04 具体方案

    .Net Core 部署到Ubuntu 16.04 中的步骤 1.安装工具 1.apache 2..Net Core(dotnet-sdk-2.0) 3.Supervisor(进程管理工具,目的是服务 ...

  7. ubuntu 安装chrome 和chromedriver

    1. chromedriver 下载地址:  https://npm.taobao.org/mirrors/chromedriver 在这里找到对应的驱动 2. 安装谷歌浏览器 2.1 安装依赖 ap ...

  8. 修饰符(动态String数组篇)--- 常用 解除疑问。

    1.无修饰符----是直接传基本类型的地址过来,并没有把基本类型的指针复制一份入栈,所以一旦修改就是修改原来的值. 2.const 修饰符 与 无修饰符一致. 3.var修饰符 与 上一致. 4.ou ...

  9. .net/c#常用框架/中间件简介

    任务调度 Quartz.NET:Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等. Quartz.NET允 许开发人员根据时间间隔 ...

  10. C# Except

    我们往往需要把一个列表中,去除另外一个列表的元素,C#提供了很好的方法,Except. 但是往往不小心就掉进坑里了. 看下面的代码: static void Main(string[] args) { ...