[CF1638C] Inversion Graph

一、题目

CF1638C
image

题目大意是给出一个排列1~p,对于i<j且pi>pj这样的i和j可以进行连接成一个块,求连接完后一共有多少个块

二、思路

不难想到,对每个块我们想维护一个maxn,然后再后面的区间里找有没有出现小于maxn的数

做法一:思维
从前往后遍历,找[1 - i]的maxn[i]
从后往前遍历,找[i + 1, n]的minn[i]
对于当前的maxn,如果后面没有minn,那么这个点就是当前块的结尾,cnt ++
否则这个块就还没有结束,继续遍历

做法二:单调栈
维护一个单调递减栈
看能否通过当前x把上一个块包含进来

三、代码

void solve() {
    vector<int> maxn, minn;
    int maxnum = 0, minnum = 1e9;
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++) {
        cin >> a[i];
    }
    for(int i = 1; i <= n; i ++) {
        if(a[i] > maxnum) maxnum = a[i];
        maxn.push_back(maxnum);
    }
    for(int i = n; i >= 1; i --) {
        minn.push_back(minnum);
        if(a[i] < minnum) minnum = a[i];
    }
    reverse(minn.begin(), minn.end());
    int cnt = 0;
    for(int i = 0; i < n; i ++) {
        if(minn[i] > maxn[i]) cnt ++;
    }
    cout << cnt << endl;
}

单调栈做法:

void solve() {
    int n;
    cin >> n;
    int x;
    int tt = 0;
    for(int i = 1; i <= n; i ++) {
        cin >> x;
        if(tt == 0 || x > stk[tt]) stk[++ tt] = x;
        else {
            int top = stk[tt --];
            while(tt && stk[tt] > x) tt --;
            stk[++ tt] = top;
        }
    }
    cout << tt << endl;
}
posted @ 2022-03-08 17:31  行舟C  阅读(56)  评论(0)    收藏  举报