首页 > 其他分享 >【题解】洛谷P5906:【模板】回滚莫队&不删除莫队

【题解】洛谷P5906:【模板】回滚莫队&不删除莫队

时间:2024-11-28 10:22:31浏览次数:9  
标签:f1 回滚 int 题解 sum -- 莫队 define

对于一些区间问题,虽然莫队好进行加操作,但并不好进行减操作,所以我们引出了回滚莫队。

【模板】回滚莫队&不删除莫队

发现我们并不总是知道什么时候取哪些值为最大值,尤其是删操作时,回滚莫队就是只用加操作实现的。

我们对询问左端点所在的块排序,相同的话按照右排序,这样对于相同的左端点的块,右端点总是单调不降的,总是加操作地向右拓展,对于左端点的块,每次向左进行加操作,结束后都回到左端点所在的块的右边界并将所有标记复原。

左右端点在同一个块内就可以直接暴力查询。

可以发现复杂度始终都是对的。

#include <bits/stdc++.h>
#define int long long
#define ls p<<1
#define rs p<<1|1 
#define re register 
#define pb push_back
#define pir pair<int,int>
#define f1(x) for(int i=1;i<=x;i++)
#define f0(x) for(int i=0;i<=x;i++)
#define fr1(x) for(int i=x;i>=1;i--)
#define fr0(x) for(int i=x;i>=0;i--) 
const int N=2e5+10,M=25005;
const int mod=1e9+7;
using namespace std;

int n,m;
int a[N],b[N]; 
int of[N],len;
int ans[N];
struct ss{
	int l,r,id;
}q[N];

bool cmp(ss g,ss h){
	return (of[g.l]^of[h.l])?of[g.l]<of[h.l]:g.r<h.r;
}
int baoli(int l,int r){
	int vis[N],sum=0;
	for(int i=l;i<=r;i++){
		vis[a[i]]=0;
	}
	for(int i=l;i<=r;i++){
		if(!vis[a[i]]){
			vis[a[i]]=i;
		}
		else{
			sum=max(sum,i-vis[a[i]]);
		}
	}
	return sum;
}

int la[N],st[N],clea[N],cn;

signed main(){
//	freopen("xp1.in","r",stdin);
    ios::sync_with_stdio(false);
    cin.tie(nullptr); 
	 
	cin>>n;
	len=sqrt(n);
	f1(n){
		cin>>a[i];
		b[i]=a[i];
		of[i]=(i-1)/len+1;
	}
	sort(b+1,b+1+n);
	int tot=unique(b+1,b+1+n)-b-1;
	f1(n){
		a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
	}
	cin>>m;
	f1(m){
		cin>>q[i].l>>q[i].r;
		q[i].id=i;
	}
	sort(q+1,q+m+1,cmp);
	
	int bn=of[n];

	for(int i=1,j=1;j<=bn;j++){//i询问数,j左边界所在块 
		int sum=0,cn=0,br=min(n,j*len),l=br+1,r=l-1;
		for(;of[q[i].l]==j;i++){
			if(of[q[i].r]==j){
				ans[q[i].id]=baoli(q[i].l,q[i].r);
				continue;
			}	
			while(r<q[i].r){
				r++;
				la[a[r]]=r;
				if(!st[a[r]]){
					st[a[r]]=r;
					clea[++cn]=a[r];
				}
				sum=max(sum,r-st[a[r]]);
			} 
			int tp=sum;
			while(l>q[i].l){
				l--;
				if(la[a[l]]){
					sum=max(sum,la[a[l]]-l);
				}
				else{
					la[a[l]]=l;
				}
			}
			ans[q[i].id]=sum;
			while(l<br+1){
				if(la[a[r]]==l){
					la[a[r]]=0;
				} 
				l++;
			} 
			sum=tp;
		}
		for(int k=1;k<=cn;k++){
			la[clea[k]]=st[clea[k]]=0;
		}
	}
	f1(m){
		cout<<ans[i]<<"\n";
	}
	return 0;
}

歴史の研究

同样维护出现次数。

#include <bits/stdc++.h>
#define int long long
#define ls p<<1
#define rs p<<1|1 
#define re register 
#define pb push_back
#define pir pair<int,int>
#define f1(x) for(int i=1;i<=x;i++)
#define f0(x) for(int i=0;i<=x;i++)
#define fr1(x) for(int i=x;i>=1;i--)
#define fr0(x) for(int i=x;i>=0;i--) 
const int N=2e5+10,M=25005;
const int mod=1e9+7;
using namespace std;

int n,m;
int a[N],b[N]; 
int of[N],len;
int ans[N];
struct ss{
	int l,r,id;
}q[N];

bool cmp(ss g,ss h){
	return (of[g.l]^of[h.l])?of[g.l]<of[h.l]:g.r<h.r;
}
int baoli(int l,int r){
	int vis[N],sum=0;
	for(int i=l;i<=r;i++){
		vis[a[i]]=0;
	}
	for(int i=l;i<=r;i++){
		vis[a[i]]++;
		sum=max(sum,vis[a[i]]*b[a[i]]);
	}
	return sum;
}

int la[N],st[N],clea[N],cn;

signed main(){
//	freopen("xp1.in","r",stdin);
    ios::sync_with_stdio(false);
    cin.tie(nullptr); 
	 
	cin>>n>>m;
	len=sqrt(n);
	f1(n){
		cin>>a[i];
		b[i]=a[i];
		of[i]=(i-1)/len+1;
	}
	sort(b+1,b+1+n);
	int tot=unique(b+1,b+1+n)-b-1;
	f1(n){
		a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
	}
	f1(m){
		cin>>q[i].l>>q[i].r;
		q[i].id=i;
	}
	sort(q+1,q+m+1,cmp);
	
	int bn=of[n];

	for(int i=1,j=1;j<=bn;j++){//i询问数,j左边界所在块 
		int sum=0,cn=0,br=min(n,j*len),l=br+1,r=l-1;
		for(;of[q[i].l]==j;i++){
			if(of[q[i].r]==j){
				ans[q[i].id]=baoli(q[i].l,q[i].r);
				continue;
			}	
			while(r<q[i].r){
				r++;
				la[a[r]]++;
				clea[++cn]=a[r];
				sum=max(sum,la[a[r]]*b[a[r]]);
			} 
			int tp=sum;
			while(l>q[i].l){
				l--;
				la[a[l]]++;
				sum=max(sum,la[a[l]]*b[a[l]]);
			}
			ans[q[i].id]=sum;
			while(l<br+1){
				la[a[l]]--;
				l++;
			} 
			sum=tp;
		}
		for(int k=1;k<=cn;k++){
			la[clea[k]]=0;
		}
	}
	f1(m){
		cout<<ans[i]<<"\n";
	}
    
	return 0;
}

标签:f1,回滚,int,题解,sum,--,莫队,define
From: https://www.cnblogs.com/sadlin/p/18573714

相关文章

  • P10398 题解
    blog。博弈论。考虑使用AGC002E的方法分析:将\(a_i\)升序排列,然后画成下图状物。一次操作相当于消掉最下面的一行/最左边的一列,消完的人胜利。将这个问题转换为:你在左下角,每次可以往上面(上面是空的就走到右上)/右边走一步,谁先走到最后一列就赢了。于是可以写出\(O(\su......
  • [题解]CF1775E The Human Equation
    来个另类解。思路手玩一下样例,发现减法只会用在正数上,加法只会用在负数上,大概是因为如何在负数上用了减法或在正数上用了加法,都需要额外的次数去消掉。然后注意到在两个正数中间包这的所有负数可以直接缩成一个数,两个负数中间包着的所有正数也可以直接缩成一个数。那么现在的序......
  • FZOUTSY 题解
    题意简述给定一个长度为\(n\)的,由特定\(7\)种字符构成的字符串,有\(m\)次询问,每次询问需要求出编号在\([l,r]\)内的后缀中,有多少对后缀的最长公共前缀长度大于等于\(k\)。题目分析注意到在所有询问中,\(k\)的值是一样的,所以我们可以考虑求出给定字符串中以第\(i\)个......
  • [题解]P8867 [NOIP2022] 建造军营
    P8867[NOIP2022]建造军营只有B国袭破坏的道路是无向图的割边时,这张图才会变得不连通,所以我们进行边双缩点,最终形成一棵树,不妨令根节点为\(1\)。记\(E[u]\)为缩点后的\(u\)包含多少条原图上的边,\(V[u]\)为\(u\)包含多少个原图上的点,并定义\(s[u]\)表示子树\(u\)中的边数。那么......
  • 龙芯3A4000的linux系统下node14.17.5运行出现Floating point exception(浮点数异常)问
    因项目需要在龙芯下使用node14.17.5执行构建任务,在使用源码编译安装后,执行时出现Floatingpointexception(浮点数异常)问题。经调试发现,其是在使用openssl加载ECC相关证书时使用mips64汇编代码时导致的。在分析相关代码后,将deps下的openssl中的bn_div.c文件的16行进行修改,重新......
  • 2023ICPC 亚洲区域赛南京站 The 2nd Universal Cup 题解 更新至 7 题
    2023ICPC亚洲区域赛南京站The2ndUniversalCup题解更新至7题Preface住院了,在医院闲得无聊自己V了一场。这场复习赛,貌似半年前还是一年前打过一次,只过了4个题。今日来还愿了。但有些题还是不会做,真的唐。我会在代码一些有必要的地方加上注释,签到题可能一般就不会写了.......
  • python问题解决-外部模块明明安装了,却总是无法找到
    1现象代码中引入了cv2模块,这是一个图像识别模块。但运行时总提示找不到该模块。也按照要求安装了opencv-python等模块。还有其它的,如python-pptx模块,提示如下:Traceback(mostrecentcalllast):File"E:/python/wps/ppt_pic.py",line1,in<module>frompp......
  • [题解]P3629 [APIO2010] 巡逻
    P3629[APIO2010]巡逻\(k=1\)时,我们一定贪心选择直径\(d\)的两个端点建立道路,所以答案是\(2\times(n-1)-d+1\)。\(k=2\)时,两条新建的道路恰好形成\(2\)个环,我们通过手玩可以发现一个结论:\(1\)条边恰好被经过\(1\)次,当且仅当它恰好位于\(1\)个环上。\(1\)条边恰好被经过\(2\)......
  • ICPC2022济南站C. DFS Order 2 题解 回滚背包
    题目链接:https://www.luogu.com.cn/problem/P9669题目大意:给你一棵包含\(n\)个节点的有根树。节点编号从\(1\)到\(n\),节点\(1\)是根节点。从节点\(1\)出发对整棵树进行深度优先遍历,会得到很多不同的DFS序。解题思路:基本上和9981day大佬的题解一模一样差不多。......
  • [网鼎杯 2020 朱雀组]phpweb 详细题解(反序列化绕过命令执行)
    知识点:call_user_func()函数反序列化魔术方法find命令查找flag代码审计打开题目,弹出上面的提示,是一个警告warning,而且页面每隔几秒就会刷新一次,根据warning中的信息以及信息中的时间一直在变,可以猜测是date()函数一直在被调用查看源代码发现一些信息,但是作用不......