Description
IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记。JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件。
日记中记录了连续N天发生的时间,大约每天发生一件。
事件有种类之分。第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大。
JOI教授决定用如下的方法分析这些日记:
1. 选择日记中连续的一些天作为分析的时间段
2. 事件种类t的重要度为t*(这段时间内重要度为t的事件数)
3. 计算出所有事件种类的重要度,输出其中的最大值
现在你被要求制作一个帮助教授分析的程序,每次给出分析的区间,你需要输出重要度的最大值。
1<=N<=10^5
1<=Q<=10^5
1<=Xi<=10^9 (1<=i<=N)
Solution
回滚莫队,get到新姿势了
对于一些能简单插入但是不能简单删除的信息可以考虑回滚莫队
一开始写的是莫队+线段树,计算一波复杂度发现并不能过就gg了
对于询问区间(l,r),我们把起点tl设为l所在块的右端点,tr设为l-1
不断右移右指针tr,记下此时答案为tmp1
不断左移左指针tl,此时答案为询问答案
将左指针tl回滚到起点(l所在块的右端点),将当前答案恢复为tmp1
如果当前询问的l与上一次询问的l所在块相同就保留左右指针,否则重新调整起点
注意到我们对询问的排序方式非常特殊,这种做法能够避开删除操作并且保持优秀的复杂度
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#define rep(i,st,ed) for (register int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
typedef long long LL;
const int N=100005;
struct Q {int l,r,id;} q[N];
int a[N],b[N],bel[N],B;
LL ans[N],vec[N],rec[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
bool cmp(Q a,Q b) {
return bel[a.l]<bel[b.l]||bel[a.l]==bel[b.l]&&(a.r<b.r);
}
int main(void) {
int n=read(),m=read(); B=sqrt(n);
rep(i,1,n) {
a[i]=read();
b[i]=a[i]; bel[i]=(i-1)/B+1;
}
std:: sort(b+1,b+n+1);
int size=std:: unique(b+1,b+n+1)-b-1;
rep(i,1,n) a[i]=std:: lower_bound(b+1,b+size+1,a[i])-b;
rep(i,1,m) q[i]=(Q) {read(),read(),i};
std:: sort(q+1,q+m+1,cmp);
int l=1,r=0;
LL tmp1=0,tmp2=0,pos;
rep(i,1,m) {
if (bel[q[i].l]!=bel[q[i-1].l]) {
fill(rec,0);
pos=l=bel[q[i].l]*B+1,r=l-1;
tmp1=tmp2=0;
}
if (bel[q[i].l]==bel[q[i].r]) {
rep(j,q[i].l,q[i].r) {
vec[a[j]]+=b[a[j]];
ans[q[i].id]=std:: max(ans[q[i].id],vec[a[j]]);
}
rep(j,q[i].l,q[i].r) vec[a[j]]-=b[a[j]];
continue;
}
for (;r<q[i].r;) { r++;
rec[a[r]]+=b[a[r]];
tmp1=std:: max(tmp1,rec[a[r]]);
}
tmp2=tmp1;
for (;l>q[i].l;) { l--;
rec[a[l]]+=b[a[l]];
tmp1=std:: max(tmp1,rec[a[l]]);
}
ans[q[i].id]=tmp1;
for (;l<pos;) {
rec[a[l]]-=b[a[l]]; l++;
}
tmp1=tmp2;
}
rep(i,1,m) printf("%lld\n", ans[i]);
return 0;
}