华为OD 特异双端队列
1. 题意
题目描述
有一个特异性的双端队列,该队列可以从头部或尾部添加数据,但是只能从头部移出数据。
小 A 依次执行 2n 个指令往队列中添加数据和移出数据:
其中 n 个指令是添加数据(可能从头部添加,也可能从尾部添加),依次添加 1 到 n;
n 个指令是移出数据。
现在要求 移除数据的顺序为 1 到 n。
为了满足输出要求,小 A 可以在任何时候调整队列中数据的顺序。
请问小 A 最少需要调整几次 才能够满足移除数据的顺序正好是 1 到 n?
2. 题解
这个题目,一开始没有仔细读题,于是直接插入双端队列,
然后进行排序。
但是题目中最重要的一个条件,依次添加1-n
。
2.1 直接排序
int n;
int ans;
int expect = 1;deque<int> dq;
string head_add_str("head add");
string tail_add_str("tail add");auto getNum = [](const std::string &s)->int {string nstr(s.begin() + 9, s.end());return stoi(nstr);};void solve1()
{
string head_add_str("head add");string tail_add_str("tail add");for (int i = 0; i < 2 * n; ++i) {string cmd;getline( cin, cmd);if ( cmd == "remove") {if ( dq.front() != expect) {ans++;sort(dq.begin(), dq.end());}dq.pop_front();++expect;}else if ( cmd.substr(0, 8) == head_add_str) {int v = getNum( cmd );dq.push_front( v );}else if ( cmd.substr(0, 8) == tail_add_str) {int v = getNum( cmd );dq.push_back( v );}}
}
2.2 根据有序性,直接赋值
由于插入时是有序的,因此我们知道最大值和最小值时就可以知道排序后的结果。直接放进队列就可以!
void solve2()
{int mx_pushed = 0;for (int i = 0; i < 2 * n; ++i) {string cmd;getline( cin, cmd);if ( cmd == "remove") {if ( dq.front() != expect) {ans++;// sort(dq.begin(), dq.end());dq.clear();for (int i = expect; i <= mx_pushed; ++i)dq.push_back(i);}dq.pop_front();++expect;}else if ( cmd.substr(0, 8) == head_add_str) {int v = getNum( cmd );dq.push_front( v );++mx_pushed;}else if ( cmd.substr(0, 8) == tail_add_str) {int v = getNum( cmd );dq.push_back( v );++mx_pushed;}}
}
2.3 空间优化
事实上我们还可以利用插入数据的有序性进一步优化!!!
我们只需要知道队列是否是有序就可以了,队列中的区间肯定是[expext,max_pushed][expext,max\_pushed][expext,max_pushed]。
而在队列后面插入一个新的元素是不会破坏队列的有序性的,只有当队列中有元素且在队列头插入新元素时,才会破坏队列的有序性!
因此我们可以将队列直接优化掉,直接维护三个变量就可以了
expect
下一次期望的出队元素max_pushed
已经入队的最大元素is_sorted
队列中的元素是否是有序的
void solve3()
{ans = 0;int mx_pushed = 0;bool is_sorted{true};for (int i = 0; i < 2 * n; ++i) {string cmd;getline( cin, cmd);if ( cmd == "remove") {if ( not is_sorted) {is_sorted = true;ans++;}++expect;}else if ( cmd.substr(0, 8) == head_add_str) {++mx_pushed;if (mx_pushed != expect)is_sorted = false;}else if ( cmd.substr(0, 8) == tail_add_str) {++mx_pushed;}}}
3. 参考
KJ.JK