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;
}

这种需要反向思考的题目需要多加注意!

posted on 2024-05-10 13:55  WHUStar  阅读(3)  评论(0编辑  收藏  举报