描述问题
小张在玩一种卡牌游戏,牌组由 2n 张牌组成,其中 n 张上写有数字 1...n 各一张,其余 n 张上全部是数字 0 。
现在牌组经过随机打乱后,小张拿走其中 n 张牌作为手牌,其余 n 张牌作为牌堆。
小张想经过若干次如下操作使得牌堆自顶向下的牌依次为 1...n 。
每一次操作,小张选择任意一张手牌放到牌堆底,并将牌堆顶的牌放入手牌。
他想知道最少进行几次操作,使得牌堆自顶向下的牌依次为 1...n 。
Input
第一行一个数 n(1 ≤ n ≤ 200000 ) 。
第二行 n 个数,表示小张手中的牌。
第三行 n 个数,表示牌堆,数组从左向右的顺序表示牌堆自顶向下的顺序。
Output
一个整数,表示最少执行的操作数。
样例
输入(1)
3
0 2 0
3 0 1
输出(1)
2
输入(2)
3
0 2 0
1 0 3
输出(2)
4
代码
#include <stdio.h>
#include <stdbool.h>
int max(int a, int b) { return a > b ? a : b; }
void input(void);
bool canReachOne(void);
void evaluate(bool);
#define MAX_SIZE 200010
int operation_count[MAX_SIZE], cards[MAX_SIZE];
int temp, num_cards, i, result = 0, additional_steps = 0;
int main(void)
{
input();
evaluate(canReachOne());
printf("%d\n", result);
return 0;
}
void input(void)
{
scanf("%d", &num_cards);
for (i = 1; i <= num_cards; i++)
{
scanf("%d", &temp);
operation_count[temp] = 0;
}
for (i = 1; i <= num_cards; i++)
{
scanf("%d", &temp);
cards[i] = temp;
operation_count[temp] = i;
}
}
bool canReachOne(void)
{
int temp;
temp = cards[num_cards];
for (i = num_cards - 1; temp != 1; i--)
{
if (cards[i] != --temp)
{
return false;
}
}
return true;
}
void evaluate(bool success)
{
bool one_loop = true;
if (success)
{
for (i = cards[num_cards] + 1; i <= num_cards; i++)
{
if (operation_count[i] > i - (cards[num_cards] + 1))
{
one_loop = false;
break;
}
}
if (one_loop)
{
result += num_cards - cards[num_cards];
}
else
{
result += num_cards + 1 + num_cards - cards[num_cards];
}
}
else
{
for (i = 1; i <= num_cards; i++)
{
temp = max(operation_count[i] - (i - 1), 0);
if (temp > additional_steps)
{
additional_steps = temp;
}
}
result += additional_steps;
result += num_cards;
}
}