题目链接:http://codeforces.com/contest/1136/problem/D
让所有能和最后一个点交换的点尽可能多且连续的排列在尾部,才能让最后一个点尽可能的排在前面,这个应该比较好理解。
这里我们假想存在这么一个队列P,最初的时候,队列P的个数为0,那么就有下面这种假想的情况存在。
a1, a2, a3, a4, [P], a5
首先存在这么一个判断,a4是否能和a5交换,如果不可以,那么就把a4这个点放到队列P里面,然后继续判断a3,
如果能和a5交换,并且能够通过题目的交换规则穿过队列P的话,那么a4和a5就能连续,否则也加入队列P里面,所以队列P就是专门存放不满足题目要求的所有点的集合。
当所有的点都考虑完之后,除了队列P以外,其他都是满足题目要求的元素。
一个点要想穿过队列P内的所有点,就必须能和P内所有元素交换。
#include <bits/stdc++.h>
using namespace std;
const int Maxn = 3e5+10;
bool p[Maxn];
vector<int> G[Maxn];
int a[Maxn];
int main(void)
{
int n, m, u, v;
scanf("%d%d", &n, &m);
for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
for(int i = 0; i < m; ++i) {
scanf("%d%d", &u, &v);
G[u].push_back(v);
}
memset(p, false, sizeof(p));
int pcnt = 0, cnt; bool ok;
for(int i = n-2; i >= 0; --i) {
ok = false; cnt = 0;
int u = a[i];
for(int j = 0; j < G[u].size(); ++j) {
int v = G[u][j];
if(v == a[n-1]) ok = true;
else if(p[v]) cnt++;
}
if(ok && cnt == pcnt) continue;
pcnt++; p[u] = true;
}
printf("%d\n", n-1-pcnt);
return 0;
}