zoukankan      html  css  js  c++  java
  • 【洛谷P5906】【模板】回滚莫队&不删除莫队

    题目

    题目链接:https://www.luogu.com.cn/problem/P5906
    给定一个序列,多次询问一段区间 ([l,r]),求区间中相同的数的最远间隔距离

    序列中两个元素的间隔距离指的是两个元素下标差的绝对值

    思路

    显然用一般的莫队处理这种问题时,要删除一个元素时并不可以做到 (O(1)) 删除。
    考虑莫队是怎么排序的?将左端点按块排序,同一个块的按照右端点从小到大排序。所以最终我们的询问的右端点一定是不超过 (sqrt{n}) 个连续递增的块。
    我们可以将每一个右端点递增的块分开来做,具体的,假设现在左端点的区间为 ((kT,(k+1)T]),其中 (T=sqrt{n}),那么我们就将 (((k+1)T,r]) 的区间利用左端点固定,右端点单调不减得性质做,对于询问的另一部分 ([l,(k+1)T]),由于这一段的长度不超过 (sqrt{n}),所以直接暴力跑就可以了。
    对于每一个块,做完之后直接 (O(n)) 清空即可。
    时间复杂度 (O(msqrt{n}))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=200010;
    int n,m,T,a[N],b[N],bel[N],last[3][N],ans[N];
    
    struct Query
    {
    	int l,r,id;
    }ask[N];
    
    bool cmp(Query x,Query y)
    {
    	return bel[x.l]==bel[y.l] ? x.r<y.r : bel[x.l]<bel[y.l];
    }
    
    int main()
    {
    	scanf("%d",&n);
    	T=sqrt(n);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		b[i]=a[i]; bel[i]=(i-1)/T+1;
    	}
    	sort(b+1,b+1+n);
    	int tot=unique(b+1,b+1+n)-b-1;
    	for (int i=1;i<=n;i++)
    		a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
    	scanf("%d",&m);
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%d%d",&ask[i].l,&ask[i].r);
    		ask[i].id=i;
    	}
    	sort(ask+1,ask+1+m,cmp);
    	int ans0,ans1,lim;
    	memset(last[2],-1,sizeof(last[2]));
    	for (int i=1,r;i<=m;i++)
    	{
    		if (bel[ask[i].l]!=bel[ask[i-1].l])
    		{
    			memset(last,-1,sizeof(last));
    			r=T*bel[ask[i].l]+1; ans0=0;
    		}
    		for (;r<=ask[i].r;r++)
    		{
    			if (last[0][a[r]]==-1) last[0][a[r]]=r;
    			last[1][a[r]]=r;
    			ans0=max(ans0,last[1][a[r]]-last[0][a[r]]);
    		}
    		ans1=0; lim=min(T*bel[ask[i].l],ask[i].r);
    		for (int j=ask[i].l;j<=lim;j++)
    		{
    			if (last[2][a[j]]==-1) last[2][a[j]]=j;
    			ans1=max(ans1,max(last[1][a[j]]-j,j-last[2][a[j]]));
    		}
    		for (int j=ask[i].l;j<=lim;j++)
    			last[2][a[j]]=-1;
    		ans[ask[i].id]=max(ans0,ans1);
    	}
    	for (int i=1;i<=m;i++)
    		printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    K2 BPM_携手东航物流,领跑全球航空物流业_全球领先的工作流引擎
    K2 BPM_如何将RPA的价值最大化?_全球领先的工作流引擎
    Sqlserver 增删该查----查
    U3D Resources AssetBundle资源打包
    Sqlserver 触发器
    Sqlserver 游标
    U3D 协程和www
    U3D 数据在安卓设备上的存储,加载
    U3D SQLite数据库
    U3D 装备的添加和移除(Unity3D)
  • 原文地址:https://www.cnblogs.com/stoorz/p/14028871.html
Copyright © 2011-2022 走看看