题解:P17720 「FunMusic OI 1C」旋律 / Melody
思路
我们观察到题目中的
我们发现,区间
由于题目中的关系是无向且具有传递性的,所以我们可以考虑使用并查集来维护连通块大小,并在合并过程中求出当前时刻连通块大小的最大值。
注意在每次左端点移动的时候要清空并查集所维护的信息。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=3100;
int fa[maxn];
int sz[maxn];
int n;
int getfa(int x)
{
if((!fa[x])||x==0||x==n+1)//该数字不在此区间中
return -1;
return fa[x]==x?x:fa[x]=getfa(fa[x]);//路径压缩
}
int ma;
void merge(int x,int y)
{
x=getfa(x);
y=getfa(y);
if(x!=-1&&y!=-1)
{
fa[x]=y;
sz[y]+=sz[x];//合并连通块大小
ma=max(ma,sz[y]);//取连通块大小最大值
}
}
int a[maxn];
int ans;
signed main()
{
cin>>n;
for (int i=1;i<=n;i++)
cin>>a[i];
for (int l=1;l<=n;l++)
{
memset(fa,0,sizeof(fa));//清空维护信息
memset(sz,0,sizeof(sz));//清空维护信息
ma=1;
for (int r=l;r<=n;r++)
{
fa[a[r]]=a[r];//并查集初始化
sz[a[r]]=1;//连通块大小初始化
merge(a[r]+1,a[r]);//合并
merge(a[r]-1,a[r]);//合并
ans+=ma;
}
}
cout<<ans;
}