zoukankan      html  css  js  c++  java
  • 回滚莫队

    听 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]
    ",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
    ",Ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Tongue Twister之scream
    把5页的内容变成2页
    Python3 字符串中的变量替换
    notepad++同时编辑多行
    获取元素属性值
    selenium定位H5表单验证的提示语
    POJ 3009 Curling 2.0(dfs)
    CCF 2016122 工资计算
    POJ 2976 Dropping tests(01分数规划二分(最大化平均值))
    POJ 2155 Matrix(二维树状数组)
  • 原文地址:https://www.cnblogs.com/juruo-zzt/p/15126118.html
Copyright © 2011-2022 走看看