题目背景
91029102 年 99 月 22 日,百度在 X 市 XX 中学举办的第一场 AI 知识小课堂大获好评!同学们对矩阵的掌握非常棒。
今天的 AI 知识小课堂的第二场开讲啦。本场 AI 知识小课堂老师教授的是数组的相关知识---上升子序列。
题目描述
给一个长度为 nn 的数组 aa 。试将其划分为两个严格上升子序列,并使其长度差最小。
输入格式
输入包含多组数据。
数据的第一行为一个正整数 TT ,表示数据组数。
每组数据包括两行:
第一行包括一个正整数 nn 。
第二行包括一个长度为 nn 的数组 aa。
输出格式
对于每组数据输出一行一个整数,表示两个子序列的最小长度差。若不存在划分方案则输出 -1−1 。
数据范围
T le 10 , n le 10^5 , a_i in [ 0 , 2^{30} ]T≤10,n≤105,ai∈[0,230] 。
特殊限制及约定:合法的划分方案数不超过 11 。
样例输入
1 6 4 1 5 2 6 3
样例输出
0
思路:
紧扣题目给的特殊约定,合法的方案数不超过1个,
那么意思就是,要么没有满足条件的方案(例如 6 个数, 分别是 6 6 6 6 6 6 ),
或者是 只有一个合法的方案数,例如样例。
这样我们从第一个数下手,如果存在一个方案,那么一定有一个lis 是以第一个数为起点的。
并且下一个比a[1] 大的数 一定被和a[1] 分在一起。
然后开始数组标记一下哪些数被分到了第一个子序列,然后剩下的子序列是否符合严格的递增的关系。
细节见代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define rt return #define dll(x) scanf("%I64d",&x) #define xll(x) printf("%I64d ",x) #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), ' ', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define db(x) cout<<"== [ "<<x<<" ] =="<<endl; using namespace std; typedef long long ll; ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} ll lcm(ll a, ll b) {return a / gcd(a, b) * b;} ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;} inline void getInt(int* p); const int maxn = 1000010; const int inf = 0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ int a[maxn]; int n; int vis[100010]; int main() { // freopen("D:\common_text\c101ode_stream\in.txt","r",stdin); //freopen("D:\common_text\code_stream\out.txt","w",stdout); int t; gbtb; cin >> t; while (t--) { MS0(vis); cin >> n; repd(i, 1, n) { cin >> a[i]; } int cnt = 1; int temp = a[1]; int num = 1; repd(i, 2, n) { if (a[i] > temp) { vis[i] = 1; temp = a[i]; num++; cnt++; } } temp = -1; repd(i, 2, n) { if (vis[i] == 0) { // cout<<i<<" "; if (temp == -1) { temp = a[i]; num++; cnt--; } if (a[i] > temp) { temp = a[i]; num++; cnt--; } } } // cout<<endl; // cout<<num<<" "<<cnt<<endl; if (num == n) { cout << abs(cnt) << endl; } else { cout << -1 << endl; } } return 0; } inline void getInt(int* p) { char ch; do { ch = getchar(); } while (ch == ' ' || ch == ' '); if (ch == '-') { *p = -(getchar() - '0'); while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 - ch + '0'; } } else { *p = ch - '0'; while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 + ch - '0'; } } }