4241: 历史研究
Time Limit: 80 Sec Memory Limit: 512 MBSubmit: 1030 Solved: 292
[ Submit][ Status][ Discuss]
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
9 8 7 8 9
1 2
3 4
4 4
1 4
2 4
Sample Output
9
8
8
16
16
8
8
16
16
HINT
1<=N<=10^5
1<=Q<=10^5
1<=Xi<=10^9 (1<=i<=N)
Source
几句闲话
orz orz neither_nor(alone_wolf).上次他讲课的时候还没有去看他这道题,后来刷这道题的时候发现他用的是回滚莫队.这道题大多人几乎都用的是分块,然而回滚莫队快的飞起.正好不会回滚莫队,赶紧学习一波.
题解
注意离散化和long long.
#include<stdio.h>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long dnt;
const int maxn=100005;
dnt ans[maxn],ed,last,tmp;
int Cnt[maxn],cnt[maxn],blo[maxn],a[maxn],b[maxn],v[maxn],block,n,m,num;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
register int x=0,f=1;
register char ch=nc();
while(ch<'0'||ch>'9'){if(ch=='-')f*=-1;ch=nc();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=nc();
return f*x;
}
struct query{
int l,r,id;
}q[maxn];
inline bool cmp(query x,query y){
if(blo[x.l]==blo[y.l]) return x.r<y.r;
return blo[x.l]<blo[y.l];
}
inline dnt calc(int lf,int rg){
register int i;ed=0;
for(i=lf;i<=rg;i++) Cnt[b[i]]=0;
for(i=lf;i<=rg;i++){
Cnt[b[i]]++;
ed=max(ed,(dnt)Cnt[b[i]]*a[i]);
}
return ed;
}
inline void update(int x){
cnt[b[x]]++;tmp=max(tmp,(dnt)cnt[b[x]]*a[x]);
}
inline void re(int x){cnt[b[x]]--;}
inline int Mo(int pos,int bl){
tmp=0;
int L=min(block*bl,n);
register int i=pos,j,ql=L+1,qr=L;
for(j=1;j<=n;j++) cnt[j]=0;
for(;blo[q[i].l]==bl;i++){
if(blo[q[i].l]==blo[q[i].r]){ans[q[i].id]=calc(q[i].l,q[i].r);continue;}
while(qr<q[i].r) update(++qr);
last=tmp;
while(ql>q[i].l) update(--ql);
ans[q[i].id]=tmp;
while(ql<L+1) re(ql++);
tmp=last;
}
return i;
}
int main(){
n=read(),m=read(),block=sqrt(n);
register int i,pos=1;
for(i=1;i<=n;i++) v[i]=a[i]=read();
sort(v+1,v+n+1);
int len=unique(v+1,v+n+1)-(v+1);
for(i=1;i<=n;i++) b[i]=lower_bound(v+1,v+1+len,a[i])-v;
for(i=1;i<=n;i++) blo[i]=(i-1)/block+1,num=max(blo[i],num);
for(i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(q+1,q+1+m,cmp);
for(i=1;i<=num;i++) pos=Mo(pos,i);
for(i=1;i<=m;i++) printf("%lld\n",ans[i]);
}