题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=4241

分析

这题就是求区间权值乘以权值出现次数的最大值,一看莫队法块可搞,但仔细想想,莫队的加入很容易,但是删除需要维护许多东西,非常麻烦,于是就有dalao想出了一个新科技--回滚莫队.回滚莫队能使操作全部变成加入或全部变成删除.这道题我们需要全部变成加入.

怎么做呢?我们对询问进行处理,左端点在一个块中的先归在一起,然后以右端点为关键字进行排序,使得右端点靠前的在前.然后依次处理按左端点归好后每个块中的询问,我们找到块中最靠后的左端点,和最靠前的右端点(其实就是块中第一个询问的右端点),统计区间信息。

对于每一个询问,先移动右端点加入元素,然后左端点左移得到询问答案后再向右移撤销,由于不需要维护什么信息撤销变得非常容易.简单来说,总的思路就是先找出最“窄”的区间,然后不断加入补全到询问区间.

当然,如果询问的左端点和右端点在一个块中就直接暴力处理

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#define LL long long
#define ri register int
using std::min;
using std::max;
using std::vector;
using std::map;
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while(!isdigit(c=getchar()))ne=c=='-';
x=c-48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;x=ne?-x:x;
return ;
}
struct Qur{
int l,r,id;
Qur(int a,int b,int c){l=a,r=b,id=c;}
bool operator <(const Qur & b)const {
return r<b.r;
}
};
const int maxn=100005;
const int maxb=355;
const int inf=0x7fffffff;
int n,w[maxn],pos[maxn];
int blo,mxl[maxb];
map <int,int> g;int tot=0,f[maxn];
int cnt[maxn];
LL res=inf,ans[maxn];
vector <Qur> qry[maxb];
inline void add(int x){
cnt[x]++;
res=max(res,1ll*cnt[x]*f[x]);
}
int main(){
int l,r,q;
read(n);read(q);
blo=sqrt(n+0.5);
memset(mxl,0,sizeof(mxl));
for(ri i=1;i<=n;i++){
read(w[i]);
if(!g[w[i]]){
g[w[i]]=++tot;
f[tot]=w[i];
}w[i]=g[w[i]];
pos[i]=(i-1)/blo+1;
}
for(ri i=1;i<=q;i++){
read(l),read(r);
if(pos[l]==pos[r]){//左端点右端点在一个块中
res=-inf;
memset(cnt,0,sizeof(cnt));
for(ri j=l;j<=r;j++)add(w[j]);
for(ri j=l;j<=r;j++)cnt[j]--;
ans[i]=res;
}
else{
qry[pos[l]].push_back(Qur(l,r,i));
mxl[pos[l]]=max(mxl[pos[l]],l);//记录询问块中的最后左端点
}
}
int ll,rr;LL last;
for(ri i=1;i<=pos[n];i++){//处理每个询问块
if(qry[i].empty())continue;
memset(cnt,0,sizeof(cnt));res=-inf;
sort(qry[i].begin(),qry[i].end());
l=mxl[i],r=qry[i][0].r;
for(ri j=l;j<=r;j++)add(w[j]);
for(ri j=0;j<qry[i].size();j++){
ll=qry[i][j].l,rr=qry[i][j].r;
while(r<rr)r++,add(w[r]);
last=res;//记录下右端点操作后信息
for(ri k=ll;k<l;k++)add(w[k]);
ans[qry[i][j].id]=res,res=last;//左端点左移后撤回
for(ri k=ll;k<l;k++)cnt[w[k]]--;//已经得到答案,撤回非常容易
}
}
for(ri i=1;i<=q;i++)printf("%lld\n",ans[i]);
return 0;
}

后记

关于这题的离散化处理,我还进行了一些比较,在这篇博客中

https://rye-catcher.github.io/2018/07/15/学习笔记-几种离散化方式/

推荐学习博客

http://isrothy.blog.uoj.ac/blog/3673

BZOJ4241历史研究题解--回滚莫队的更多相关文章

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

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

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

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

  3. BZOJ4241 历史研究 【回滚莫队】

    题目描述:给出一个长度为\(n\)的数组,每次询问区间 \([l,r]\),求 \(\max\limits_{x}x*cnt_x\),其中 \(cnt_x\) 表示 \(x\) 在区间 \([l,r] ...

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

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

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

    题意:给定N个数字,Q次询问,询问这个区间的最大加权众数是多少. 加权众数是指出现次数*数字大小.N,Q<1e5. 思路:不难发现可以N*sqrtN*logN的思路做,但是应该过不了. 这个Ns ...

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

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

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

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

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

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

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

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

随机推荐

  1. pytorch-mnist神经网络训练

    在net.py里面构造网络,网络的结构为输入为28*28,第一层隐藏层的输出为300, 第二层输出的输出为100, 最后一层的输出层为10, net.py import torch from torc ...

  2. MySQL 如何使用show processlist进行过滤

    在使用show processlist的时候,直接使用会显示很多的内容,无法很快找到需要的信息. 如何过滤操作呢? 其实,show processlist展示的内容是从information_sche ...

  3. 【SR汇总】基于深度学习方法

    1.SRCNN.FSRCNN (Learning a Deep Convolutional Network for Image Super-Resolution, ECCV2014) (Acceler ...

  4. 10 MySQL之数据备份与恢复

    01-数据备份 # 1.使用 MySQLdump 命令备份 MySQLdump 是MySQL提供的一个非常有用的数据库备份工具. MySQLdump 命令执行时,可以将数据库备份成一个文本文件,该文本 ...

  5. JDK8记FullGC时候Metaspace内存不会被垃圾回收

    本文链接:https://blog.csdn.net/a15939557197/article/details/90635460背景前段时间有一个这样的需求:第三方调用接口,30分钟内调用120W次: ...

  6. mysql安装报错error: Header V3 DSA signature: BAD, key ID

    CentOS安装rpm安装MySQL时爆出警告: warning: mysql-community-server-5.7.18-1.el6.x86_64.rpm: Header V3 DSA/SHA1 ...

  7. SqlServer:SqlServer(服务器磁盘监控,创建管理员账号分配权,添加链接服务器,查询CPU,查询内存)

    1.服务器磁盘监控 (1)总链接服务上开启所有链接服务器的RPC: ----------------------总链接服务器上面,开启每个服务器的RPC --exec sp_serveroption ...

  8. SpringBoot搭建聚合项目-实战记录01

    工具:Spring Tool Suite 4 项目搭建 1.首先建立工作集 : Configure Working Sets -> New.. ->设置名称(如project) -> ...

  9. 【Java开发】Maven那点事儿(Eclipse版)

    Maven那点事儿(Eclipse版) 前言: 由于最近工作学习,总是能碰到Maven的源码.虽然平时工作并不使用Maven,但是为了学习一些源码,还是必须要了解下.这篇文章不是一个全面的Maven解 ...

  10. 深入理解C语言-深入理解指针

    关于指针,其是C语言的重点,C语言学的好坏,其实就是指针学的好坏.其实指针并不复杂,学习指针,要正确的理解指针. 指针是一种数据类型 指针也是一种变量,占有内存空间,用来保存内存地址 指针就是告诉编译 ...