Codeforces 1136D Nastya Is Buying Lunch (贪心)
题意:给你和一个数组(是一个排列)和一些二元组,二元组(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\n", ans);
}
---恢复内容结束---

浙公网安备 33010602011771号