[BZOJ4241]历史研究(回滚莫队)

将整个序列分成$\sqrt{n}$块,所有询问按左端点所在块为第一关键字,右端点所在块为第二关键字排序。

当右端点增加或左端点减小时,更新桶与答案。但是左端点增加时需要删除,这时就必须用堆等数据结构维护,复杂度多一个log。

回滚莫队是一个trick:

1.按同样的方法对所有询问排序,每次处理左端点在同一个块中的所有询问。

2.若对于当前询问,右端点和左端点在同一个块中,暴力即可。

3.否则,右端点照常加入更新,左端点先设为块尾,再不断减小,更新答案后再还原至块尾。

这样每次只有左端点减小时才会更新答案,不再需要删除操作。

复杂度分析基本与普通莫队相同。

对于左右端点所属块相同的询问,单次复杂度显然$O(\sqrt{n})$

对于左右端点所属块不同的询问,右端点的处理并没有区别,故总复杂度仍是$(n\sqrt{n})$。左端点每次都只在一个块中移动,故总复杂度也是$(n\sqrt{n})$

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=100010,B=300;
 9 ll ans[N];
10 int n,Q,cnt[N],a[N],b[N],bel[N];
11 struct P{ int l,r,id; }q[N];
12 bool cmp(const P &a,const P &b){ return (bel[a.l]==bel[b.l]) ? a.r<b.r : bel[a.l]<bel[b.l]; }
13 
14 int main(){
15     freopen("bzoj4241.in","r",stdin);
16     freopen("bzoj4241.out","w",stdout);
17     scanf("%d%d",&n,&Q);
18     rep(i,1,n) scanf("%d",&a[i]),b[i]=a[i],bel[i]=(i-1)/B+1;
19     rep(i,1,Q) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
20     sort(b+1,b+n+1); int tot=unique(b+1,b+n+1)-b-1;
21     rep(i,1,n) a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
22     sort(q+1,q+Q+1,cmp); int i,j;
23     for (i=1; i<=Q; i=j){
24         int t=bel[q[i].l],r=min(n,B*t),l=r+1; ll mx=0;
25         memset(cnt,0,sizeof(cnt));
26         for (j=i; j<=Q && bel[q[j].l]==t; j++){
27             if (bel[q[j].r]==t){
28                 rep(k,q[j].l,q[j].r) cnt[a[k]]++,mx=max(mx,1ll*b[a[k]]*cnt[a[k]]);
29                 rep(k,q[j].l,q[j].r) cnt[a[k]]--;
30                 ans[q[j].id]=mx; mx=0;
31             }else{
32                 while (r<q[j].r) cnt[a[++r]]++,mx=max(mx,1ll*b[a[r]]*cnt[a[r]]);
33                 ll tmp=mx;
34                 while (l>q[j].l) cnt[a[--l]]++,mx=max(mx,1ll*b[a[l]]*cnt[a[l]]);
35                 ans[q[j].id]=mx;
36                 while (l<=B*t) cnt[a[l++]]--;
37                 mx=tmp;
38             }
39         }
40     }
41     rep(i,1,Q) printf("%lld\n",ans[i]);
42     return 0;
43 }

 

 

posted @ 2018-11-02 19:03  HocRiser  阅读(223)  评论(0编辑  收藏  举报