回滚莫队

听 jmr 讲数据结构听到自闭,于是痛定思痛决定补一补技能点。

主要参考 ouuan 的博客

算法流程

同普通莫队,对询问端点进行分块,对于左右端点在同一块的询问直接暴力计算。

bool cmp(Query a,Query b){return a.bl!=b.bl?a.l<b.l:a.r<b.r;}

排序之后,询问左端点 \(l\) 换块时清空答案,这时对于这一块的询问右端点 \(r\) 是单调递增的。对于同一块内的询问,先将莫队的 \(L\) 设为下一块的起始点,然后将莫队的 \(R\) 向右移动至 \(r\),然后 \(L\) 移动至 \(l\)。此次询问处理完之后将 \(ans\) 回滚会 \(L\) 移动之前的答案,并且将 \(L\) 重新设为下一块的起点。可以证明复杂度仍然是 \(\mathcal O(n^{1.5})\) 级别。

例题

LOJ#2874. 「JOISC 2014 Day1」历史研究

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#include<cstdlib>
using namespace std;
#define mp make_pair
#define pb push_back
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long ull;
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
const int N=1e5+10;
int cnt[N],t[N],a[N];
ll ans,Ans[N];
void add(int x)
{
	cnt[x]++;
	ans=max(ans,1ll*t[x]*cnt[x]);
}
struct Query{int l,r,pos,bl;}q[N];
bool cmp(Query x,Query y){return x.bl==y.bl?x.r<y.r:x.l<y.l;}
int main()
{
	int n=read(),m=read(),sz=sqrt(n),cnt1=0;
	for(int i=1;i<=n;i++)a[i]=t[i]=read();
	int c=n;sort(t+1,t+c+1),c=unique(t+1,t+c+1)-t-1;
	for(int i=1;i<=n;i++)a[i]=lower_bound(t+1,t+c+1,a[i])-t;
	for(int i=1;i<=m;i++)
	{
		int l=read(),r=read();
		if(l/sz==r/sz)
		{
			ans=0;
			for(int j=l;j<=r;j++)cnt[a[j]]++,ans=max(ans,1ll*cnt[a[j]]*t[a[j]]);
			Ans[i]=ans;
			ans=0;
			for(int j=l;j<=r;j++)cnt[a[j]]=0;
		}
		else q[++cnt1]=Query{l,r,i,l/sz};
	}
	sort(q+1,q+cnt1+1,cmp);
	for(int i=1,L=1,R=0;i<=cnt1;i++)
	{
//		printf("[%d, %d]\n",q[i].l,q[i].r);
		if(q[i].bl!=q[i-1].bl||i==1)
		{
			memset(cnt,0,sizeof(cnt));
			L=(q[i].bl+1)*sz;
			R=(q[i].bl+1)*sz-1;
			ans=0;
		}
		while(R<q[i].r)add(a[++R]);
		ll tmp=ans;
		while(L>q[i].l)add(a[--L]);
		Ans[q[i].pos]=ans;
		while(L<(q[i].bl+1)*sz)cnt[a[L]]--,L++;
		ans=tmp;
	}
	for(int i=1;i<=m;i++)printf("%lld\n",Ans[i]);
	return 0;
}
posted @ 2021-08-10 22:32  zzt1208  阅读(88)  评论(1编辑  收藏  举报