codeforce-1136-D(546-D)

我的博客链接:https://startcraft.cn

题目链接:https://codeforces.com/contest/1136/problem/D


题目大意:
给你1-n的n个数,给出一个序列,序列由这n个数组成,然后给m对数u,v,一对数u,v代表在序列中如果u和v相邻,且u在v的左边,则可以交换这两个数,现在问你序列中的最后一个数最多可以向左移动几次


思路:设序列中最后一个数为x,考虑哪些数在x的左边时可以将x向左移动,将这些数用一个集合V记录下来。
用一个指针pos指向最后一个数,然后看pos左边的数是不是这些记录下来的数中的一个,如果是的话就交换这两个数,并且将左边这个数从集合V中删除,然后pos-1,ans++,如果不是,则看pos左边这个数y,看可以将y向左移动的数有哪些,将这些数与V求交集然后更新V,因为X只能与V中的数交换,所以能与y交换的数若不在V中就不能使得X左移,然后让pos指向y,重复上面的过程,直到V为空集或者指着走到最左边

AC代码:

#include <iostream>
#include <set>
#include <queue>
#include <cstdio>
using namespace std;
typedef long long ll;
#define wfor(i,j,k) for(i=j;i<k;++i)
#define mfor(i,j,k) for(i=j;i>=k;--i)
// void read(int &x) {
//  char ch = getchar(); x = 0;
//  for (; ch < '0' || ch > '9'; ch = getchar());
//  for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
// }
const int maxn = 3e5 + 5;
int num[maxn];
int vis[maxn];
set<pair<int, int>>st;
int main()
{
    std::ios::sync_with_stdio(false);
#ifdef test
    freopen("F:\\Desktop\\question\\in.txt", "r", stdin);
#endif
#ifdef ubuntu
    freopen("/home/time/debug/debug/in", "r", stdin);
    freopen("/home/time/debug/debug/out", "w", stdout);
#endif
    int n, m;
    cin >> n >> m;
    int i;
    wfor(i, 0, n)
    {
        cin >> num[i];
    }
    queue<int>can;
    wfor(i, 0, m)
    {
        int u, v;
        cin >> u >> v;
        if (v == num[n - 1])
        {
            can.push(u);//记录可以使得num[n-1]向左移动的数
            vis[u] = 1;
        }
        st.insert(make_pair(u, v));
    }
    int pos = n - 1;
    int ans = 0;
    while (pos > 0 && !can.empty())
    {
        if (vis[num[pos - 1]] == 1)//可以向左移动
        {
            ans++;
            vis[num[pos - 1]] = 0;//从集合中删除这个数
            swap(num[pos - 1], num[pos]);
        } else//不可以移动,求交集,更新集合
        {
            int len = can.size();
            wfor(i, 0, len)
            {
                int t = can.front();
                can.pop();
                if (vis[t])//这个数未被集合剔除
                {
                    if (st.count(make_pair(t, num[pos - 1])) != 0)//看num[pos-1]可否通过t换到左边去(求交集的过程)
                    {
                        can.push(t);
                    } else
                        vis[t] = 0;
                }
            }
        }
        pos--;
    }
    cout << ans << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章