[CF1638C] Inversion Graph
一、题目
题目大意是给出一个排列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;
}


浙公网安备 33010602011771号