题目: 传送门
思路:
很明显,如果编号为 i 的同学要跟编号 为 j 的同学交换位置,他必须能跟它们之间所有的人都能交换,这样 i 同学才能到达j同学的前面相邻的位置,而这样对 j 同学的位置的贡献只是向前 +1 位.
有了上述的结论,那么对于最后一个位置的同学也是如此,而且从贪心的角度来考虑,我们肯定先考虑离最后一位同学当前位置最近的人能不能交换,如果能就直接交换 ans++,如果不能,那么我们就通过所有以它结尾二元组更新之前还未遍历到的位置.
注: 如果该位置能交换,我们就不能使用其二元组的贡献,因为能贡献它一定在 初始最后一个同学当先位置的后面。
虽然思路不难,但是实现的过程有点难懂,大家且看且珍惜.
参考代码:
int n,m,ans;
int a[300050];
int cnt[300050];
vector<int> v[300050];
int main() {
cin>>n>>m;
for(int i=1;i<=n;i++) {
cin>>a[i];
}
int x,y;
for(int i=0;i<m;i++) {
cin>>x>>y;
v[y].push_back(x);
}
for(int i=0;i<v[a[n]].size();i++) {
cnt[v[a[n]][i]]++;
}
for(int i=n-1;i>=1;i--) {
if(n-i-ans == cnt[a[i]]) ans++;
else {
for(int j=0;j<v[a[i]].size();j++) {
cnt[v[a[i]][j]]++;
}
}
}
cout<<ans<<endl;
return 0;
}