CF652C Foe Pairs 题解

考虑双指针,枚举左端点 ii,看右端点 jj 最多拓展到哪里。

我们对每个点开个 vector,存这个点选了之后哪些的另一个不能选。

对于 jj,如果存在这个点的 vector 内的数 kk 满足 ik<ji \leq k < j,那么 jj 就不能作为右端点了。我们直接对于每个点的 vector 存一下 <j<j 的最大值,看一下是否大于等于 ii 就可以做到拓展时 O(1)O(1) 判断了。

#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
using namespace std;

const int N = 3e5 + 5;
int n, a[N], m;
int l[N], r[N];
int pos[N];
vector<int> gg[N];
int maxn[N],minn[N];

signed main()
{
	ios::sync_with_stdio(0), cin.tie(0);
	memset(maxn,0,sizeof maxn);
	memset(minn,0x3f,sizeof minn);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		pos[a[i]]=i;
	}
	for(int i=1;i<=m;i++)
	{
		cin>>l[i]>>r[i];
		gg[pos[r[i]]].emplace_back(pos[l[i]]);
		gg[pos[l[i]]].emplace_back(pos[r[i]]);
	}
	for(int i=1;i<=n;i++)
	{
		for(auto&j:gg[i]) 
		{
			if(j>=i) continue;
			maxn[i]=max(maxn[i],j),minn[i]=min(minn[i],j);
		}
	}
	long long ans=0;
	int j=1;
	for(int i=1;i<=n;i++)
	{
		j=max(j,i);
		while(j<=n)
		{
			if(maxn[j]>=i) goto E;
//			for(auto&k:gg[j])
//			{
//				if(k<j&&k>=i)
//				{
//					goto E;
//				}
//			}
			j++;
		}
		E:;
		ans+=j-i;
	//	cout<<"!!!: " << i << " " << j << "\n";
	}
	cout<<ans<<"\n";
	return 0;
}
posted @   HappyBobb  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示