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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章