Codeforces 1463D Pairs

題意node

對於數字\(1\)~\(2n\),能夠構造出\(n\)個二元組,對於\(n\)個二元組,選擇一個數組\(x\),留下\(x\)個二元組的最小值,留下\(n-x\)個二元組的最大值,其構成了一個集合。ios

如今給定一個集合\(b\),問有多少種\(x\)的取值能夠獲得該集合。c++

分析數組

首先斷定的是\(x\),因此對於任意\(x\)來講,前\(x\)個必定爲留下的最小值,不然若\(x<y\),且\(x\)爲取的最大值而\(y\)爲取的最小值,那不妨交換\(x\)\(y\)一樣知足條件。那麼咱們只須要斷定每個\(x\)的取值是否合法。spa

假設當前取值爲\(i\),那麼對於前\(i\)個數,均可以找到一個比其大的數配對,而對於後\(n-i\)個數,均可以找到一個比其小的數配對。貪心的將丟棄的數放置在一個\(set\)中,對於前\(i\)個數,貪心的找到最小的比其大的數,如果沒法找到,則表示該位置沒法取值。一樣對於後\(n-i\)個數,貪心的找到其最大的比其小的數,如果沒法找到,則表示該位置沒法取值。code

咱們能夠發現一個性質,若是第\(i\)個位置是可行的,那麼要保證前\(i\)個數是能夠有配對數的,同時後\(n-i\)個數也是能夠有配對數的,那麼咱們正着判斷前\(i\)個數,反着判斷後\(n-i\)個數,判斷完後掃一遍便可。ci

#pragma GCC optimize(3, "Ofast", "inline")

#include <bits/stdc++.h>

#define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define ull unsigned long long
#define int ll
#define ls st<<1
#define rs st<<1|1
#define pii pair<int,int>
#define rep(z, x, y) for(int z=x;z<=y;++z)
#define repd(z, x, y) for(int z=x;z>=y;--z)
#define com bool operator<(const node &b)const
using namespace std;
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
const int maxn = (ll) 1e6 + 5;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
int T = 1;
int a[maxn];
int n;
bool pre[maxn], last[maxn];

void solve() {
    cin >> n;
    set<int> s, t;
    rep(i, 1, 2 * n)s.insert(i), t.insert(i);
    rep(i, 1, n) {
        pre[i] = last[i] = false;
        int x;
        cin >> x;
        s.erase(x);
        t.erase(x);
        a[i] = x;
    }
    sort(a + 1, a + n + 1);
    int ans = 0;
    rep(i, 1, n) {
        while (!s.empty() && *s.begin() < a[i])
            s.erase(s.begin());
        if (s.empty())
            break;
        if (*s.begin() > a[i])
            s.erase(s.begin());
        else
            break;
        pre[i] = true;
    }
    repd(i, n, 1) {
        while (!t.empty() && *(--t.end()) > a[i])
            t.erase(--t.end());
        if (t.empty())
            break;
        if (*(--t.end()) < a[i])
            t.erase(--t.end());
        else
            break;
        last[i] = true;
    }
    pre[0] = last[n + 1] = true;
    rep(i, 0, n)ans += (pre[i] && last[i + 1]);
    cout << ans << '\n';
}

signed main() {
    start;
    cin >> T;
    while (T--)
        solve();
    return 0;
}
相關文章
相關標籤/搜索