CF1773E Easy Assembly
链接:https://codeforces.com/problemset/problem/1773/E
思路
首先先得出最终序列,因为它具有唯一性,然后再根据其中的前后关系来判断原来的数列需要切几刀。然后再根据切几刀形成的最终数列判断需要合并几次。
例如:
目标数列是ABCDEF,而给出的某两段序列是ADBC,EF,那么必要的解法一定是在A后面切一刀,D后面切一刀,然后合并。
本题代码采用两个vector记录:第一个lst记录最终序列,第二个each记录原有的n分段序列,然后通过补0判断是否本来就是缺口位(即结尾),通过遍历each改变cut,最后修改merge为n+cut-1即可。
代码:
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<cmath>
#include<limits.h>
#include<climits>
#include<fstream>
#include<set>
typedef long long ll;
using namespace std;
const ll N = 3e5 + 10;
vector<ll>lst;
vector<ll>each;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
ll cut = 0, merge = 0;
map<int, int>mp;
int n; cin >> n;
for (int i = 0; i < n; i++)
{
int k; cin >> k;
for (int i = 0; i < k; i++)
{
ll now; cin >> now;
lst.push_back(now), each.push_back(now);
}
each.push_back(0);
}
sort(lst.begin(), lst.end());
for (int i = 0; i < lst.size(); i++)
mp[lst[i]] = i;
for (ll i = 0; i < each.size(); i++)
if (each[i] and each[i+1])
if (mp[each[i + 1]] != mp[each[i]] + 1)
cut++;
merge = n + cut - 1;
cout << cut << ' ' << merge;
return 0;
}
这种需要反向思考的题目需要多加注意!