题意:给你和一个数组(是一个排列)和一些二元组,二元组(x, y)表示如果x正好在y前面而且相邻,那么x和y可以交换位置,问最后一个元素最多可以向前移动多少步?
思路:对于每个数,有两种选择,一种是向后走,一种是向前走。假设我们决定让这个数向前走,那么把所有以它结尾的二元组的cnt加1。cnt代表的是后面有多少个数可以与这个数合并。假设当前位置是i,若n - i - ans == cnt[i],说明这个数可以与最后一个数合并,ans加1。因为若满足这个等式,说明存在一种方法,让最后一个数恰好与i交换成功一次。
代码:
#include <bits/stdc++.h> #define LL long long #define lowbit(x) (x & (-x)) #define pii pair<int, int> #define INF 0x3f3f3f3f using namespace std; const int maxn = 300010; int cnt[maxn]; vector<int> c[maxn]; int a[maxn]; int main() { int n, m, x, y; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int i = 1; i <= m; i++) { scanf("%d%d", &x, &y); c[y].push_back(x); } for (int i = 0; i < c[a[n]].size(); i++) cnt[c[a[n]][i]]++; int ans = 0; for (int i = n - 1; i >= 1; i--) { if(n - i - ans == cnt[a[i]]) ans++; else { for (int j = 0; j < c[a[i]].size(); j++) cnt[c[a[i]][j]]++; } } printf("%d ", ans); }
---恢复内容结束---