# BZOJ4241 历史研究 （分块 回滚莫队-教程向）

## 代码

/**************************************************************
Problem: 4241
User: CHN
Language: C++
Result: Accepted
Time:9968 ms
Memory:5592 kb
****************************************************************/

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;

register int val=0; char ch;
while(~(ch=getchar()) && (ch<'0' || ch>'9')); val=ch-'0';
while(~(ch=getchar()) && (ch>='0' && ch<='9')) val=(val<<1)+(val<<3)+ch-'0';
return val;
}

const int maxn=int(1e5)+111;
int n,m;
int a[maxn], b[maxn], v[maxn];
int siz, num, bel[maxn];
long long ans[maxn];

struct Q {
int l,r,id;
bool operator < (const Q &b) const {
return bel[l]==bel[b.l]?r<b.r:bel[l]<bel[b.l];
}
}q[maxn];

register int i;
for(i=1;i<=n;++i)

sort(v+1,v+1+n);
int nn=unique(v+1,v+1+n)-(v+1);
for(i=1;i<=n;++i)
b[i]=lower_bound(v+1,v+1+nn,a[i])-v;

for(i=1;i<=m;++i) {
q[i].id=i;
}
while(siz*siz<n) ++siz;
for(i=1;i<=n;++i)
bel[i]=(i-1)/siz+1, num=max(num,bel[i]);
sort(q+1,q+1+m);
return;
}

long long tmp=0;
int cnt[maxn];

++cnt[b[id]];
tmp=max(tmp,1ll*cnt[b[id]]*a[id]);
}
void Del(int id) {
--cnt[b[id]];
}

long long small(int l,int r) {
static int cnt2[maxn];
long long res=0;
register int i;
for(i=l;i<=r;++i)
cnt2[b[i]]=0;
for(i=l;i<=r;++i) {
++cnt2[b[i]];
res=max(res,1ll*cnt2[b[i]]*a[i]);
}
return res;
}

int Mo(int pos,int id) {
int L=min(id*siz,n);
register int i=pos,j, ql=L+1, qr=ql-1;
for(j=1;j<=n;++j) cnt[j]=0;
tmp=0;
for(;bel[q[i].l]==id;++i) {
if(bel[q[i].l]==bel[q[i].r]) {
ans[q[i].id]=small(q[i].l,q[i].r);
continue;
}
long long cur=tmp;
ans[q[i].id]=tmp;
while(ql<L+1) Del(ql++);
tmp=cur;
}
return i;
}

void Solve() {
register int i,pos=1;
for(i=1;i<=num;++i)
pos=Mo(pos,i);
return;
}

int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
Solve();

for(int i=1;i<=m;++i)
printf("%lld\n",ans[i]);

return 0;
}
08-17 5797
03-06 1602

05-20 1万+
07-18 150
11-02 797
11-30 2668