题目链接:
New Year and Ascent Sequence - 洛谷
思路:
题目说了,只要两者拼起来的序列中有递增子序列,就是符合题意的序列。我们可以反向考虑:计算所有不符合题意的序列数量,然后用n*n减去这个数,就是最终答案。
首先,内部有递增子序列的串,不管和谁拼起来都是满足题意的,所以不考虑这些串。我们只记录内部没有递增子序列的串的最大值和最小值,然后枚举每个记录了的串,记录不能接在它后面的串的数量,mn[ i ] >= mx[ j ]说明 j 不能接在 i 的后面。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int inf = 0x3f3f3f3f;
const int maxn = 1e5+5;
int n, cnt = 0, len; //cnt表示不符合题意的组合个数
int mx[maxn], mn[maxn]; //序列的最大最小值
int idx = 0;
signed main(){
cin >> n;
for(int i=0; i<n; i++){
int maxVal = 0, minVal = inf;
bool flag = false;
cin >> len;
for(int j=1; j<=len; j++){
int x; cin >> x;
if(x > minVal) flag = true;
maxVal = max(maxVal, x);
minVal = min(minVal, x);
}
if(!flag) {mx[idx] = maxVal; mn[idx] = minVal; idx++;}
//内部有递增子序列的串,必定符合题意,不用考虑
}
sort(mx, mx+idx);
for(int i=0; i<idx; i++){
int tmp = upper_bound(mx, mx+idx, mn[i])-mx;
//mx数组中有tmp个 <= mn[i]的数字,他们对应的序列接在i的后面都不能满足题意
cnt += tmp;
}
cout << n*n-cnt << '\n';
}