CF652C Foe Pairs 题解
考虑双指针,枚举左端点 ,看右端点 最多拓展到哪里。
我们对每个点开个 vector,存这个点选了之后哪些的另一个不能选。
对于 ,如果存在这个点的 vector 内的数 满足 ,那么 就不能作为右端点了。我们直接对于每个点的 vector 存一下 的最大值,看一下是否大于等于 就可以做到拓展时 判断了。
#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;
}

浙公网安备 33010602011771号