首页 > 其他分享 >【bzoj4358】permu【XSY1535】seq(莫队+并查集)

【bzoj4358】permu【XSY1535】seq(莫队+并查集)

时间:2022-10-28 20:01:34浏览次数:57  
标签:fa1 return seq int 查集 permu ins fa2 莫队

考虑莫队,但是我们发现这个东东只支持\(ins\)(至于怎么支持等会再讲),不支持\(del\)操作,所以我们构造一种只\(ins\)不\(del\)的莫队。

由于我们按莫队的方法排序,第一关键字为\(l\)所在的块,第二关键字为\(r\)。所以当排完序后,肯定是当\(l\)所在的块相同时,\(r\)单调递增,所以我们对\(l\)所在的块相同的询问进行处理。设对于块\(B\),它的末尾位置为\(end\),我们先找出在排完序中的数组中所有\(l\)所在的块为\(B\)的询问\(q_1\)、\(q_2\)……\(q_k\),那么这些询问肯定在数组中是连续的,而且它们的\(r\)肯定单调递增。

然后这些询问肯定是长这样的:

在这里插入图片描述

既然\(r\)单调递增,那么对于\(r\)我们直接\(ins\)就好了。而对于\(l\),由于\(l\)都在块\(B\)里,所以我们每个询问直接从\(end\)暴力向左\(ins\)就可以了。

至于\(ins\)操作,我们考虑用并查集维护。对于插入的每一个值\(x\),我们在值域中找到它,并把它分别和\(x-1\)和\(x+1\)所在并查集连起来(如果没有就不连),那么答案就是所有并查集中最大的\(size\)。

代码如下:

#include<bits/stdc++.h>

#define N 50010

using namespace std;

struct Question
{
	int l,r,block,id;
}q[N];

int n,m,len,block,a[N],ed[N],ans,Ans[N],st[N],top;
int fa1[N],size[N];
int fa2[N],minn[N],maxn[N];

int find1(int x)
{
	return fa1[x]==x?x:fa1[x]=find1(fa1[x]);
}

int find2(int x)
{
	return fa2[x]==x?x:fa2[x]=find2(fa2[x]);
}

int get(int x)
{
	return (x-1)/len+1;
}

bool operator < (Question a,Question b)
{
	return a.block==b.block?a.r<b.r:a.l<b.l;
}

void add1(int u)
{
	int v;
	fa1[u]=u,size[u]=1;
	if(v=find1(u-1))
		fa1[v]=u,size[u]+=size[v];
	if(v=find1(u+1))
		fa1[v]=u,size[u]+=size[v];
	ans=max(ans,size[u]);
}

void add2(int u,int &Ans)
{
	int v;
	st[++top]=u;
	fa2[u]=u,minn[u]=maxn[u]=u;
	if(v=find2(u-1))minn[u]=minn[v];
	else if(v=find1(u-1)) minn[u]-=size[v];
	if(v=find2(u+1))maxn[u]=maxn[v];
	else if(v=find1(u+1)) maxn[u]+=size[v];
	Ans=max(Ans,maxn[u]-minn[u]+1);
	if(minn[u]!=u)fa2[minn[u]]=u,st[++top]=minn[u];
	if(maxn[u]!=u)fa2[maxn[u]]=u,st[++top]=maxn[u];
}

int main()
{
	scanf("%d%d",&n,&m);
	block=len=sqrt(n);
	while(block*len<n)block++;
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1,edd=len;i<=block;i++,edd=min(edd+len,n))
		ed[i]=edd;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&q[i].l,&q[i].r);
		q[i].block=get(q[i].l),q[i].id=i;
	}
	sort(q+1,q+m+1);
	for(int p=1,i=1;i<=m;i=p+1,p=i)
	{
		memset(fa1,0,sizeof(fa1));
		ans=0;
		while(q[i].block==q[p+1].block)p++;
		int now=ed[q[i].block];
		for(int j=i;j<=p;j++)
		{
			while(now<q[j].r)add1(a[++now]);
			Ans[q[j].id]=ans;
			for(int k=q[j].l;k<=min(q[j].r,ed[q[j].block]);k++)
				add2(a[k],Ans[q[j].id]);
			while(top)
				fa2[st[top--]]=0;
		}
	}
	for(int i=1;i<=m;i++)
		printf("%d\n",Ans[i]);
	return 0;
}

标签:fa1,return,seq,int,查集,permu,ins,fa2,莫队
From: https://www.cnblogs.com/ez-lcw/p/16837303.html

相关文章

  • 【ARC074E】RGB Sequence(神奇的dp)
    注意到颜色的种类数只有\(3\)种,\(n\leq100\)也很小。然后就有了一种神奇的dp状态:考虑从前往后填方块,设\(dp(i,j,k)\)表示离当前位置最近的颜色位置在\(i\),离当......
  • Pytorch----入门级CIFAR10的神经网络层,sequential,tansorboard可视化卷积中的各种参
    文章目录​​普通方法​​​​完整代码:​​​​sequential方法​​​​使用tansorboard可视化卷积层中的各种数据​​普通方法使用神经网络:(CIFAR10的神经网络)可以看到......
  • 7.CF438D The Child and Sequence 线段树维护区间取模
    7.CF438DTheChildandSequence线段树维护区间取模给定数列,区间查询和,区间取模,单点修改。记录区间最大值,对于区间最大值小于模数的区间不予更新洛谷传送门:​​CF438DT......
  • 并查集--翻译机的个数(顺丰2020年笔试)
    某学术会议上,一共有n个人参加,现在已知每个人会的语言(一个人可能不会任何语言)。现在有一种学习机,每一个学习机可以在会议期间使一个人暂时掌握一种自己不会的语言,问要使得任......
  • 并查集--村村通
    题目描述某市调查城镇交通状况,得到现有城镇道路统计表。表中列出了每条道路直接连通的城镇。市政府“村村通工程”的目标是使全市任何两个城镇间都可以实现交通(但不一定有直......
  • 并查集--同时修路得到的最短时间
    题目背景AA地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车。政府派人修复这些公路。题目描述给出A地区的村庄数NN,和公路数MM,公路是双向的。并告诉你每条公路的连......
  • STL函数之全排列next_permutation
    题目描述牛牛的作业薄上有一个长度为n的排列A,这个排列包含了从1到n的n个数,但是因为一些原因,其中有一些位置(不超过10个)看不清了,但是牛牛记得这个数列顺序对的数量是k,顺......
  • mysqlsequence并发
    mysql有sequence吗在该目录中创建一个小型php文件(info.php的)在浏览器中调用它。该文件将显示很多关于我们的php安装,如安装的php版本和有用的一些细节。如何用navicatpre......
  • ACWing - 4493 -- 思维题&&并查集&&dfs
    题目描述环形连通分量思路对于一个无向图中的简单环(环中边的数量等于点的数量),有一个很强的性质:每个点的度数等于\(2\)。那么我们只需要先找出所有的连通块,然后判......
  • CF1743B Permutation Value
    题链:cfluogu构造。Description构造一个\(1\simn\)的排列,使之连续子串构成\(1\simk\)排列的数目最少。Analysis显然,最小数目可以为\(2\)。因为可以构造所示......